#sql #aggregate #non-equi-join
#sql #совокупный #неравнозначное объединение
Вопрос:
Учитывая две таблицы с именами team и award, мне нужно присвоить командам награды на основе ранга каждой команды. Вот две таблицы:
Команда
team_id | Имя | ранг |
---|---|---|
1 | звезды | 4 |
2 | черви | 2 |
3 | птицы | 1 |
4 | собаки | 3 |
5 | облака | 5 |
6 | бронкос | 8 |
7 | Автомобили | 11 |
8 | llamas | 7 |
9 | кошки | 9 |
10 | саранча | 6 |
11 | буллы | 10 |
награда
пороговое значение | количество |
---|---|
1 | 10000.00 |
2 | 7000.00 |
3 | 5000.00 |
6 | 2000.00 |
10 | 500.00 |
Командам должны быть присвоены награды, подобные этой:
ранг | пороговое значение | количество |
---|---|---|
1 | 1 | 10000.00 |
2 | 2 | 7000.00 |
3 | 3 | 5000.00 |
4 | 6 | 2000.00 |
5 | 6 | 2000.00 |
6 | 6 | 2000.00 |
7 | 10 | 500.00 |
8 | 10 | 500.00 |
9 | 10 | 500.00 |
10 | 10 | 500.00 |
11 | null | null |
Я никогда раньше не использовал неравнозначное объединение, но подумал, что это может быть классическим примером, когда неравнозначное объединение было бы полезно. Я написал этот запрос MySQL, который дает нужные мне результаты:
SELECT t.name, t.rank, MIN(a.threshold) AS threshold, MAX(a.amount) AS amount
FROM team AS t
INNER JOIN award AS a ON t.rank <= a.threshold
GROUP BY t.team_id
ORDER BY t.rank;
Имя | ранг | пороговое значение | количество |
---|---|---|---|
птицы | 1 | 1 | 10000.00 |
черви | 2 | 2 | 7000.00 |
собаки | 3 | 3 | 5000.00 |
звезды | 4 | 6 | 2000.00 |
облака | 5 | 6 | 2000.00 |
саранча | 6 | 6 | 2000.00 |
llamas | 7 | 10 | 500.00 |
бронкос | 8 | 10 | 500.00 |
кошки | 9 | 10 | 500.00 |
буллы | 10 | 10 | 500.00 |
Мой вопрос таков: «Есть ли проблемы с использованием неравнозначного соединения, которые я не понимаю?» Или, другими словами, «Существует ли более стандартный подход SQL к этой проблеме?»
Комментарии:
1. Какой механизм базы данных?
2. Я использую MySQL, но меня также интересуют ответы для других систем баз данных.
Ответ №1:
Также стандартным, но не входящим в каждую СУБД, является БОКОВОЕ ОБЪЕДИНЕНИЕ.
SELECT t.team_id, t.name, t.rank
, award.threshold
, award.amount
FROM team t
CROSS JOIN LATERAL (
select
min(a.threshold) as threshold
, max(a.amount) as amount
from award a
where a.threshold >= t.rank
) award
ORDER BY t.rank;
Это похоже на коррелированный подзапрос.
Но вы можете получить из него больше столбцов.