Случай T-SQL, когда существует запрос, не дающий ожидаемых результатов - PullRequest
0 голосов
/ 06 сентября 2018

Я собрал запрос, который должен показывать каждую запись, в которой есть события до и после выбранной даты. С добавленным дополнительным столбцом, который будет установлен в True / False, если у записи есть события до даты, и то же самое, если у записи есть события после второй даты.

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

SELECT DISTINCT DeviceName,dPhone,DSIMID,  Vehicles.reg, DeviceID,
CASE
WHEN EXISTS (SELECT eventID FROM [events] WHERE [events].sysdatetime < 
'2018-09-05 11:46:00.000')
THEN 'True' ELSE 'False' 
END AS [WasReportingBeforeDate],
CASE
WHEN EXISTS (SELECT eventID FROM [events] WHERE [events].sysdatetime > 
'2018-09-05 11:46:00.000')
THEN 'True' ELSE 'False' END AS [WasReportingAfterDate]
FROM [Devices]
INNER JOIN Vehicles ON Vehicles.DevID = Devices.DevID
INNER JOIN [events] ON Devices.DevID = [events].DeviceID;

Пример токового выхода:

Z3243   1  1 AA05 AAA 1 True    True

Ожидаемый результат:

Z3243   1  1 AA05 AAA 1 True    False

Нет данных для этой записи более поздней, чем вторая дата, поэтому она должна вернуть false

Ответы [ 3 ]

0 голосов
/ 06 сентября 2018

Вы не коррелируете свой EXISTS, поэтому, если какая-либо запись существует в таблице с [events].sysdatetime > '2018-09-05 11:46:00.000', тогда ваш EXISTS всегда будет возвращать true.

Вы хотите что-то вроде этого:

...
CASE WHEN EXISTS (SELECT *
                  FROM [events] e2
                  WHERE e2.sysdatetime > '2018-09-05 11:46:00.000'
                  AND e2.eventID = e.eventID) --here
...
FROM [Devices] d
INNER JOIN Vehicles v ON b.DevID = d.DevID
INNER JOIN [events] e ON d.DevID = e.DeviceID;
0 голосов
/ 06 сентября 2018
  1. Избавьтесь от соединения с events и не стесняйтесь удалять лишние DISTINCT
  2. Поместите предикат объединения в подзапросы, в которых он сейчас отсутствует

вот так:

SELECT DeviceName,dPhone,DSIMID,  Vehicles.reg, DeviceID,
CASE
  WHEN EXISTS (SELECT 1 FROM [events] e 
    WHERE e.sysdatetime < '2018-09-05 11:46:00.000'
    AND e.DeviceID = Devices.DevID)
  THEN 'True' ELSE 'False' 
END AS [WasReportingBeforeDate],
CASE
  WHEN EXISTS (SELECT 1 FROM [events] e 
    WHERE e.sysdatetime > '2018-09-05 11:46:00.000'
    AND e.DeviceID = Devices.DevID)
THEN 'True' ELSE 'False' END AS [WasReportingAfterDate]
FROM [Devices]
INNER JOIN Vehicles ON Vehicles.DevID = Devices.DevID
0 голосов
/ 06 сентября 2018

Я бы разбил запрос на 2 отдельных запроса и использовал union all, чтобы снова вернуть набор результатов вместе. Если вам нужен флаг для определения событий, прежде чем вы сможете жестко закодировать это в следующих запросах.

   ;WITH EventsBefore AS 
    (
    SELECT DISTINCT
           DeviceName,
           dPhone,
           DSIMID,
           Vehicles.reg,
           DeviceID,
    FROM [Devices]
         INNER JOIN Vehicles ON Vehicles.DevID = Devices.DevID
         INNER JOIN [events] ON Devices.DevID = [events].DeviceID
         INNER JOIN lastEvent ON Devices.DevID = lastEvent.devID;
    WHERE [events].sysdatetime < '2018-09-05 11:46:00.000'

    )

     ,EventsAfter AS 
    (
    SELECT DISTINCT
           DeviceName,
           dPhone,
           DSIMID,
           Vehicles.reg,
           DeviceID,
    FROM [Devices]
         INNER JOIN Vehicles ON Vehicles.DevID = Devices.DevID
         INNER JOIN [events] ON Devices.DevID = [events].DeviceID
         INNER JOIN lastEvent ON Devices.DevID = lastEvent.devID;
    WHERE WHERE [events].sysdatetime > '2018-09-05 11:46:00.000'

    )

    SELECT * FROM EventsBefore
    UNION ALL 
    SELECT * FROM EventsAfter
...