假设我有一个名为AT_Devices的SQL表,每个记录代表一块硬件。我有一个名为AT_Event_History的第二个表,它描述了硬件的“事件”。事件可能包括丢失,毁坏,退役等设备。每个事件都有相应的状态代码。
我写了一些SQL来返回AT_Devices中每条记录的最新事件的代码。我有一个业务规则,如果设备没有记录事件,状态代码应为0。
在这种情况下,我写了我的SQL查询返回0,但由于某种原因,它返回NULL。为什么呢?
SELECT atDeviceHistory.StatusCodeNotNull AS StatusCode0
FROM dbo.AT_Devices atd LEFT OUTER JOIN
(
SELECT DeviceID,
ParentCode,
(CASE WHEN (StatusCode IS NOT NULL) THEN StatusCode ELSE 0 END) AS
StatusCodeNotNull,
WhenEntered AS StatusDate
FROM AT_Event_History as A
WHERE A.ParentCode=0
AND A.WhenEntered >= (SELECT MAX(WhenEntered)
FROM AT_Event_History AS B
WHERE A.DeviceID=B.DeviceID AND ParentCode=0)
) atDeviceHistory ON atd.DeviceID=atDeviceHistory.DeviceID
答案 0 :(得分:4)
由于您正在执行left join
,如果没有匹配的记录,则会为引用atDeviceHistory
列的任何内容返回空值。如果您不想返回不匹配的记录,请将其更改为inner join
。我还建议您将案例陈述更改为COALESCE
:
SELECT DeviceID,
ParentCode,
COALESCE(StatusCode ,0) AS StatusCodeNotNull,
WhenEntered AS StatusDate
FROM AT_Event_History as A
更新:
试试这个:
SELECT COALESCE(atDeviceHistory.StatusCode,0) AS StatusCode0
FROM dbo.AT_Devices atd LEFT OUTER JOIN
(
SELECT DeviceID,
ParentCode,
StatusCode
WhenEntered AS StatusDate
FROM AT_Event_History as A
WHERE A.ParentCode=0
AND A.WhenEntered >= (SELECT MAX(WhenEntered)
FROM AT_Event_History AS B
WHERE A.DeviceID=B.DeviceID AND ParentCode=0)
) atDeviceHistory ON atd.DeviceID=atDeviceHistory.DeviceID
答案 1 :(得分:0)
现在@Abe Miessler has pointed out错误的NULL检查你的查询,你实际上可以摆脱子选择并重写整个查询,如下所示:
SELECT
COALESCE(h.StatusCode, 0) AS StatusCode0,
… /* whatever other columns you might need */
FROM dbo.AT_Devices atd
LEFT OUTER JOIN AT_Event_History h ON atd.DeviceID = h.DeviceID
AND h.ParentCode = 0
AND h.WhenEntered = (SELECT MAX(WhenEntered)
FROM AT_Event_history
WHERE DeviceID = a.DeviceID AND ParentCode = 0)