Return table b 中日期最接近但大于现在的记录 NOW(),对于 table a 中的每条记录
Return the record with the date closest to but greater than now NOW() in table b, for each record in table 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
我只想获得有未来约会的参与者,并且我只想 return 如果他们未来约会的位置是移动位置类型,我只想获得这些参与者。但是,我只关心他们最近约会的地点。我需要在单个查询中执行此操作。我已经到了这个阶段,在那里我能够获得所有地点的位置类型,对于所有比现在更大的约会,对于所有人,但我需要将其限制在他们未来最近的约会并且我不知道如何继续。
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 支持Window Functions;因此,一种方法是根据您的要求简单地连接表,然后按 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
值的行获得行号 = 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
服务器版本: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
我只想获得有未来约会的参与者,并且我只想 return 如果他们未来约会的位置是移动位置类型,我只想获得这些参与者。但是,我只关心他们最近约会的地点。我需要在单个查询中执行此操作。我已经到了这个阶段,在那里我能够获得所有地点的位置类型,对于所有比现在更大的约会,对于所有人,但我需要将其限制在他们未来最近的约会并且我不知道如何继续。
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 支持Window Functions;因此,一种方法是根据您的要求简单地连接表,然后按 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
值的行获得行号 = 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