У меня есть библиотека книг (books
) и другая таблица, где каждый раз, когда кто-то book_loans
книгу или возвращает книгу, она записывается (book_loans
).
В принципе, я хочу видеть все книги, которые были выписаны в определенное время, сколько:
Я хочу сделать это все сразу, и сейчас я использую 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 запросов.
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
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;
Это альтернатива juugen d с аналогичными результатами; но я бы пошел со своим первым. В отличие от его, в этом случае книга, соответствующая нескольким условиям, будет включена только в первое условие.
Однако, если таблица book_loans ОЧЕНЬ велика, вы все равно можете рассмотреть включение условий OR в предложение WHERE.
Это должно делать то, что вам нужно, если вам просто нужен общий счет, где все 3, или, если вам нужно 3 разных итоговых значения, по одному для каждого OR, вам нужно что-то другое.
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
)