Возвращает запись с датой, ближайшей к текущей, но большей, чем сейчас, в таблице b для каждой записи в таблице a
Версия сервера: 10.3.15-MariaDB-log
У меня есть такая структура данных
TABLE A - Participant
participantID
--------------
1
2
3
4
TABLE B - Appointment
appointmentID | participantID | locationID | beginDateTime
----------------------------------------------------------------
1 | 1 | 1 | 2019-10-09 11:00:00
2 | 1 | 1 | 2019-10-10 11:00:00
3 | 2 | 2 | 2019-10-11 11:00:00
4 | 3 | 3 | 2019-11-09 11:00:00
5 | 5 | 1 | 2019-10-15 11:00:00
TABLE C - Location
locationID | locationTypeID
----------------------------
1 | 1
2 | 2
3 | 3
TABLE D - Location Type
locationTypeID | locationType
-----------------------------
1 | mobile
2 | onsite
3 | unknown
Я хочу получить только тех участников, у которых назначена встреча в будущем, и я хочу вернуть этих участников только в том случае, если место их будущей встречи является мобильным. Однако меня волнует только место их ближайшей встречи. Мне нужно сделать это одним запросом. Я дошел до этого этапа, на котором я могу получить locationType для всех мест, для всех встреч больше, чем сейчас, для всех людей, но мне нужно ограничить это только их ближайшей встречей в будущем, и я не знаю, как продолжить.
SELECT p.participantID
FROM locationType AS lt
LEFT JOIN location AS l ON l.locationTypeID = lt.locationTypeID
LEFT JOIN appointment AS a ON a.locationID = l.locationID
LEFT JOIN participant AS p ON p.participantID = a.participantID
WHERE p.participantID IN (
SELECT a.participantID
FROM appointment AS a
LEFT JOIN location AS l ON l.locationID = a.locationID
LEFT JOIN locationType AS lt ON lt.locationTypeID = l.locationTYpeID
WHERE a.beginDateTime > NOW()
AND l.locationTypeID IN (
SELECT locationTypeID
FROM locationType
WHERE locationType = 'mobile'
)
);
1 ответ
MariaDB 10.3 поддерживает оконные функции; Итак, один из способов - просто присоединиться к таблицам в соответствии с вашими требованиями, а затем вычислить номер строки в порядке возрастанияbeginDateTime
. После этого вы можете использовать результат в качестве подзапроса и рассматривать только те строки, номер строки которых равен 1.
ROW_NUMBER() OVER(PARTITION BY p.participantID ORDER BY a.beginDateTime ASC)
: Он разбивает все строки вместе, имея одинаковые p.participantID
ценность. Это похоже наGROUP BY
, но главное отличие здесь в том, что GROUP BY
объединяет их в одну строку, а PARTITION BY
поддерживает их как отдельные строки. Теперь, в пределах определенного раздела определенного значенияp.participantID
, он присваивает номер строки отдельным строкам в порядке возрастания beginDateTime
ценность. Итак, строка с наименьшимbeginDateTime
value получает номер строки = 1, второй наименьший как 2 и т. д. Поскольку вам нужна ближайшая строка datetime, мы можем просто рассмотреть строку, номер строки которой равен 1.
SELECT * FROM
(
SELECT p.participantID,
ROW_NUMBER() OVER(PARTITION BY p.participantID
ORDER BY a.beginDateTime ASC) AS rn
FROM locationType AS lt
JOIN location AS l ON l.locationTypeID = lt.locationTypeID
JOIN appointment AS a ON a.locationID = l.locationID
AND a.beginDateTime > NOW()
JOIN participant AS p ON p.participantID = a.participantID
WHERE lt.locationType = 'Mobile'
) dt
WHERE rn = 1