T-SQL 存在查询未产生预期结果的情况
T-SQL Case When Exists Query Not Producing Expected Results
我整理了一个查询,该查询应显示在选定日期之前和之后发生事件的每条记录。添加了一个额外的列,如果记录在日期之前有事件,该列将设置为 True/False,如果记录在第二个日期之后有事件,则设置为 True/False。
问题是我知道事件 table 中有记录在第一个日期之前而不是在第二个日期之后,但它们没有出现在我的查询中。只有两者都为 True 的结果才会从查询中出来。不确定我做错了什么。
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
此记录没有比第二个日期更新的数据,因此它应该 return false
我会将查询分成 2 个单独的查询,然后使用 union all 将结果集 return 再次组合在一起。如果您需要一个标志来确定事件,然后才能将其硬编码到以下查询中。
;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
您没有关联您的 EXISTS
,因此如果 table 中存在任何记录与 [events].sysdatetime > '2018-09-05 11:46:00.000'
,那么您的 EXISTS
将始终 return 为真.
你想要这样的东西:
...
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;
- 摆脱加入
events
并随意删除多余的 DISTINCT
- 将连接谓词放入现在缺少它的子查询中
像那样:
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
我整理了一个查询,该查询应显示在选定日期之前和之后发生事件的每条记录。添加了一个额外的列,如果记录在日期之前有事件,该列将设置为 True/False,如果记录在第二个日期之后有事件,则设置为 True/False。
问题是我知道事件 table 中有记录在第一个日期之前而不是在第二个日期之后,但它们没有出现在我的查询中。只有两者都为 True 的结果才会从查询中出来。不确定我做错了什么。
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
此记录没有比第二个日期更新的数据,因此它应该 return false
我会将查询分成 2 个单独的查询,然后使用 union all 将结果集 return 再次组合在一起。如果您需要一个标志来确定事件,然后才能将其硬编码到以下查询中。
;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
您没有关联您的 EXISTS
,因此如果 table 中存在任何记录与 [events].sysdatetime > '2018-09-05 11:46:00.000'
,那么您的 EXISTS
将始终 return 为真.
你想要这样的东西:
...
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;
- 摆脱加入
events
并随意删除多余的DISTINCT
- 将连接谓词放入现在缺少它的子查询中
像那样:
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