【问题标题】:Better way to get counts of data in this query? [duplicate]在此查询中获取数据计数的更好方法? [复制]
【发布时间】:2018-07-06 19:12:41
【问题描述】:

我有一个图书馆 (books) 和另一个桌子,每次有人借书或带回一本书时,它都会被记录下来 (book_loans)。

基本上我想查看在某个时间签出的所有书籍,有多少:

  • 属于“奇幻”类型
  • 超过 500 页
  • 是精装书

我想一次完成所有这些,我现在使用 4 个查询,有没有更好的方法?

PS:book_loans.bookID 是books.id 的外键:

SELECT * FROM
(

    SELECT COUNT(*) FROM `books` AS bks
    INNER JOIN `book_loans` AS bs ON bks.id = bs.bookID
    WHERE bs.time = '2017-07-01 02:16:00' AND bs.signedout = 1 AND bks.genre = 'fantasy'

    UNION

    SELECT COUNT(*) FROM `books` AS bks
    INNER JOIN `book_loans` AS bs ON bks.id = bs.bookID
    WHERE bs.time = '2017-07-01 02:16:00' AND bs.signedout = 1 AND bks.pages > 500


    UNION

    SELECT COUNT(*) FROM `books` AS bks
    INNER JOIN `book_loans` AS bs ON bks.id = bs.bookID
    WHERE bs.time = '2017-07-01 02:16:00' AND bs.signedout = 1 AND bks.hardcover = 1

) x;

为此总共执行 4 个查询似乎效率很低。

【问题讨论】:

    标签: mysql sql select foreign-keys union


    【解决方案1】:
    SELECT SUM(bks.genre = 'fantasy') as fantasy,
           SUM(bks.pages > 500) as pages,
           SUM(bks.hardcover = 1) as hardcover
    FROM `books` AS bks
    INNER JOIN `book_loans` AS bs ON bks.id = bs.bookID
    WHERE bs.time = '2017-07-01 02:16:00' AND bs.signedout = 1
    

    【讨论】:

    • 非常感谢!
    【解决方案2】:

    如果您只想要全部 3 个的总数,或者,如果您需要 3 个不同的总数,每个总数一个,或者您需要不同的东西,这应该可以满足您的需要。

    SELECT COUNT(*) FROM `books` AS bks
    INNER JOIN `book_loans` AS bs ON bks.id = bs.bookID
    WHERE bs.time = '2017-07-01 02:16:00' AND bs.signedout = 1 
    AND (
        bks.genre = 'fantasy'
        OR bks.pages > 500
        OR bks.hardcover = 1
    )
    

    【讨论】:

      【解决方案3】:
      SELECT CASE WHEN bks.genre = 'fantasy' THEN 'genre match' 
                  WHEN bks.pages > 500 THEN 'page count met' 
                  WHEN bks.hardcover = 1 THEN 'is hardcover'
             END AS condition
            , COUNT(*) 
      FROM `books` AS bks
      INNER JOIN `book_loans` AS bs ON bks.id = bs.bookID
      WHERE bs.time = '2017-07-01 02:16:00' AND bs.signedout = 1 
        AND (bks.genre = 'fantasy' OR bks.pages > 500 OR bks.hardcover = 1)
      GROUP BY condition;
      

      这是 juergen d's 的替代方法,具有相似的结果;但我会先和他一起去。与他不同的是,在这本书中,匹配多个条件的书只会包含在第一个条件的计数中。

      但是,如果 book_loans 表非常大,您仍可以考虑在 WHERE 子句中包含 OR 条件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-20
        • 1970-01-01
        • 1970-01-01
        • 2011-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多