服务器版本: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'
)
);
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