为什么我的SQL查询返回NULL为空?它永远不应该返回NULL行

时间:2012-05-17 17:29:18

标签: sql

假设我有一个名为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

2 个答案:

答案 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)