简体   繁体   English

对于表a中的每条记录,返回表b中日期最接近但大于now()的记录

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM