Вы можете объединить эти три таблицы вместе с аналитической функцией rank()
в порядке убывания для count
в подзапросе, а затем принять меньше, чем пять в основном запросе:
SELECT authorid, authorfirstname, authorlastname
FROM
(
SELECT a.authorid, a.authorfirstname, a.authorlastname,
rank() over (order by count(*) desc) as rnk
FROM AUTHOR a
LEFT JOIN BOOK bk ON a.authorid = bk.authorid
LEFT JOIN BORROWER br ON br.bookid = bk.bookid
WHERE br.borrowdate between date'2017-01-01' and date'2017-12-31'
GROUP BY a.authorid, a.authorfirstname, a.authorlastname
)
WHERE rnk <= 5
ORDER BY rnk
Есливы используете БД версии 12c +, проще извлечь их:
SELECT a.authorid, a.authorfirstname, a.authorlastname,
rank() over (order by count(*) desc) as rnk
FROM AUTHOR a
LEFT JOIN BOOK bk ON a.authorid = bk.authorid
LEFT JOIN BORROWER br ON br.bookid = bk.bookid
WHERE br.borrowdate between date'2017-01-01' and date'2017-12-31'
GROUP BY a.authorid, a.authorfirstname, a.authorlastname
ORDER BY rnk
FETCH FIRST 5 ROWS WITH TIES
, где я использовал br.borrowdate between date'2017-01-01' and date'2017-12-31'
вместо to_char(br.borrowdate) like '%2017'
, чтобы иметь возможность использовать индекс для столбцаborrowdate
если существует любой.
Эти запросы возвращают строки со связями, например, они приносят больше строк, чем пять, при условии, что несколько строк соответствуют значению 5-й строки.
Doне используйте rownum
псевдостолбец для ранжирования, так как его значение вычисляется до упорядочения и может привести к неверным результатам.