#mysql #sql #datetime #subquery #greatest-n-per-group
#mysql #sql #datetime #подзапрос #наибольшее число на группу
Вопрос:
У меня есть следующие две таблицы
FlightTable
| passenger_id | flight_date | flight_number | destination |
| -------------| ---------- | -------------- | ------------ |
| 1234 | 2020-12-16 | 534 | CA |
| 1234 | 2020-12-29 | 876 | FL |
| 1234 | 2020-11-13 | 938 | FL |
| 5678 | 2020-12-27 | 986 | MN |
| 5678 | 2020-11-19 | 347 | WA |
Таблица пассажиров
| passenger_id | company_name | phone_number |
| -------------| ------------ | ------------ |
| 1234 | Verizon | (555) 874-9232 |
| 5678 | ATamp;T | (555) 867-5309 |
Я хочу создать временную таблицу, которая включает определенные столбцы из обеих таблиц, но включает только строку из FlightTable, которая имеет последнюю дату flight_date, происходящую до 2020-12-28 для каждого пассажира. Результирующая таблица должна выглядеть следующим образом:
TempTable
| passenger_id | company_name |flight_number | destination |
| -------------| ------------ |------------ | ------------ |
| 1234 | Verizon |534 | CA |
| 5678 | ATamp;T |986 | MN |
Я безуспешно пытался выполнить следующий запрос:
CREATE TEMPORARY TABLE TempTable AS (
SELECT F.passenger_id, P.company_name, flight_number, destination
FROM FlightTable AS F, PassengerTable AS P
WHERE '2020-12-28' <= MAX(flight_date) AND F.passenger_id = P.passenger_id
);
Как это можно изменить, чтобы работать должным образом?
Ответ №1:
Во-первых, научитесь использовать правильный JOIN
синтаксис. Затем вы можете использовать коррелированный подзапрос, чтобы выбрать самую последнюю дату перед вашим отсечением:
SELECT F.passenger_id, P.company_name, f.flight_number, f.destination
FROM FlightTable F JOIN
PassengerTable P
ON F.passenger_id = P.passenger_id
WHERE f.flight_date = (SELECT MAX(f2.flight_date)
FROM FlightTable f2
WHERE f2.passenger_id = f.passenger_id AND
f2.flight_date < '2012-12-28'
);
Ответ №2:
Один из вариантов использует подзапрос:
select p.passenger_id, p.company_name, f.flight_number, f.destination
from passenger p
inner join flight f on f.passenger_id = p.passenger_id
where f.flight_date = (
select max(f1.flight_date)
from flight f1
where f1.passenger_id = f.passenger_id and f1.flight_date < '2020-12-28'
)
В качестве альтернативы вы можете использовать оконные функции:
select p.passenger_id, p.company_name, f.flight_number, f.destination
from passenger p
inner join (
select f.*,
rank() over(partition by passenger_id order by flight_date desc) rn
from flight f
where flight_date < '2020-12-28'
) f on f.passenger_id = p.passenger_id
where rn = 1