[英]Return the record with the date closest to but greater than now NOW() in table b, for each record in table a
Server Version: 10.3.15-MariaDB-log服务器版本: 10.3.15-MariaDB-log
I have a data structure like this我有这样的数据结构
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
I only want to get participants who have an appointment that is in the future, and I only want to return those participants if the location of their future appointment is a mobile location type.我只想获取将来有约会的参与者,并且如果他们未来约会的位置是移动位置类型,我只想返回这些参与者。 However I only care about the location of their nearest future appointment.
但是,我只关心他们最近的约会地点。 I need to do this in a single query.
我需要在单个查询中执行此操作。 I have gotten to this stage, where I am able to get the locationType of all locations, for all appointments greater than now, for all people, but I need to limit this to only their nearest appointment in the future and am not sure how to proceed.
我已经到了这个阶段,在那里我可以获取所有位置的 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'
)
);
MariaDB 10.3 supports Window Functions ; MariaDB 10.3 支持Window 功能; so, one way is to simply join the tables based on your requirements, and then calculate row number in ascending order of
beginDateTime
.因此,一种方法是根据您的要求简单地加入表,然后按
beginDateTime
的升序计算行号。 Afterwards, you can use the result as a subquery and consider only those rows where the row number is 1.之后,您可以将结果用作子查询并仅考虑行号为 1 的那些行。
ROW_NUMBER() OVER(PARTITION BY p.participantID ORDER BY a.beginDateTime ASC)
: It partitions all the rows together having same p.participantID
value. ROW_NUMBER() OVER(PARTITION BY p.participantID ORDER BY a.beginDateTime ASC)
:它将所有具有相同p.participantID
值的行分区在一起。 It is like GROUP BY
, but the main difference here is that GROUP BY
aggregates them into a single row, while PARTITION BY
maintains them as individual rows.它就像
GROUP BY
,但这里的主要区别是GROUP BY
将它们聚合到一行中,而PARTITION BY
将它们维护为单独的行。 Now, within a specific partition of a specific value of p.participantID
, it assigns a row number to individual rows in the ascending order of beginDateTime
value.现在,在
p.participantID
的特定值的特定分区内,它按beginDateTime
值的升序为各个行分配一个行号。 So, the row with lowest beginDateTime
value gets row number = 1, second lowest as 2, and so on.. Since you want the nearest datetime row, we can then simply consider the row whose row number is 1.因此,具有最低
beginDateTime
值的行获得行号 = 1,第二低为 2,依此类推。由于您想要最近的日期时间行,因此我们可以简单地考虑行号为 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.