Как уже объяснили другие: «Вы не можете съесть свой пирог и съесть его».
Вы либо группируете по что-то, и можете вернуть его как есть, либо что-то собрать.В вашем случае вы хотите группировать по магазинам, то есть иметь отдельную строку результатов для магазина (которая соответствует критериям внутреннего объединения), но не по сотруднику.В этом случае должны быть агрегированы данные сотрудника, которые включают имя.
Классическая агрегация берет все записи в группе, поэтому вы должны использовать все имена сотрудников в агрегации, а это не то, что вам нужно, а простосотрудник с максимальной зарплатой.
К счастью, в Oracle DB есть что-то для таких случаев (хотя, возможно, не для всех), и это модификатор агрегатных функций KEEP
с его DENSE_RANK
иLAST
/ FIRST
.
Эта конструкция позволяет выполнять агрегирование на подмножестве строк в группе, где то, что вы KEEP
в агрегации, составляет FIRST
или LAST
вназначенный рейтинг (на основе заданных критериев заказа).В вашем случае вам нужно будет заказать сотрудников в группе (сотрудников магазина) на основе критерия заработной платы, и таким образом агрегация будет ограничена наиболее высокооплачиваемыми сотрудниками.Предполагая, что зарплаты являются уникальными значениями (которые они обычно не являются), это даст вам подгруппу из одного сотрудника, так что вы можете применить любую агрегацию, которую вы хотите (часто MAX
или MIN
), и все же получить этоодно имяЕсли предположить, что значения заработной платы не являются уникальными, то может быть более одного сотрудника с максимальной зарплатой - на первом месте есть связь.В этом случае вы либо вводите тай-брейк в порядок ранжирования (например, второстепенные критерии после зарплаты могут быть именем работы), либо решаете проблему на уровне агрегации (например, выбирая сотрудника MAX
или MIN
имя).
В целом мы получаем что-то вроде этого:
SELECT MAX(e.ename)
KEEP (DENSE_RANK FIRST ORDER BY e.sal DESC NULLS LAST, e.job) AS name,
MIN(e.job)
KEEP (DENSE_RANK FIRST ORDER BY e.sal DESC NULLS LAST, e.job) AS job,
e.store_id,
MAX(e.sal) AS salary,
s.city
FROM employees e
INNER JOIN stores s ON e.store_id = s.store_id
GROUP BY e.store_id, s.sity