Найти запись, ближайшую к указанной дате и времени - PullRequest
3 голосов
/ 04 апреля 2019

Я пытаюсь получить данные из таблицы, которая ближе всего к указанной дате и времени, например, как вы можете видеть ниже немного данных о дверях, и если они открыты и закрыты в определенное время. Я должен был получить список дверей, сгруппированных по DoorTitle ближе к определенному времени. Пример данных ниже

Id    DoorTitle    Status    DateTime
1     Door_1       OPEN      2019-04-04 9:16:22
2     Door_2       CLOSED    2019-04-01 15:46:54
3     Door_3       CLOSED    2019-04-04 12:23:42
4     Door_2       OPEN      2019-04-02 23:37:02
5     Door_1       CLOSED    2019-04-04 19:56:31

Допустим, я хочу выяснить статус дверей, если они открыты или закрыты в 2019-04-04 23:54:55, чтобы дать мне записи, сгруппированные по названию двери, ближайшей к тому времени. Я пробовал этот запрос, но он дает мне записи, наиболее близкие к этому времени, он просто случайным образом выбирает их, проверяя, меньше ли DateTime, чем 2019-04-04 23:54:55.

SELECT DoorTitle,Status,DateTime 
FROM Doors 
WHERE DateTime <= '2019-04-04 23:54:55'  
GROUP BY DoorTitle;

Результаты, которые я хочу получить после выполнения запроса, - это список дверей, сгруппированных по DoorTitle, ближайший к дате и времени, т. Е. 2019-04-04 23:54:55, указанный, как показано ниже, должен возвращать эти результаты, но используемый мной запрос не возвращает мне этого.

DoorTitle    Status    DateTime
Door_3       CLOSED    2019-04-04 12:23:42
Door_2       OPEN      2019-04-02 23:37:02
Door_1       CLOSED    2019-04-04 19:56:31

Дайте мне знать, какой SQL-запрос я могу использовать для достижения этой цели и как мой запрос неверен. Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 04 апреля 2019

Я бы использовал коррелированный подзапрос с условием NOT EXISTS:

SELECT DoorTitle, Status, DateTime
FROM Doors t
WHERE 
    DateTime < '2019-04-04 23:54:55'
    AND NOT EXISTS (
        SELECT 1
        FROM Doors t1
        WHERE  t1.DateTime < '2019-04-04 23:54:55' AND t1.DateTime > t.DateTime
    )

Условие NOT EXISTS обеспечивает отсутствие записи, ближайшей к целевой дате.

2 голосов
/ 04 апреля 2019

Не используйте агрегацию.Используйте фильтрацию:

SELECT d.*
FROM Doors d
WHERE d.DateTime = (SELECT MAX(d2.DateTime)
                    FROM doors d2
                    WHERE d2.DoorTitle = d.DoorTitle AND
                          d2.DateTime <= '2019-04-04 23:54:55'
                   );

Производительность должна быть разумной с индексом на doors(DoorTitle, DateTime).

1 голос
/ 04 апреля 2019

Вы можете рассчитать последнее время и дату для каждой двери, а затем объединить результаты с исходной таблицей:

SELECT Doors.*
FROM (
    SELECT DoorTitle, MAX(DateTime) AS MaxDateTime
    FROM Doors
    WHERE DateTime <= '2019-04-04 23:54:55'
    GROUP BY DoorTitle
) AS sq
JOIN Doors ON sq.DoorTitle = Doors.DoorTitle AND sq.MaxDateTime = Doors.DateTime
...