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

为什么我的SQL查询返回空的行?它不应该返回空值的行,sql,Sql,假设我有一个名为AT_Devices的SQL表,每个记录代表一个硬件。我还有一个名为AT_Event_History的表,它描述了硬件部件发生的“事件”。一个事件可以由诸如设备丢失、毁坏、报废等事件组成。每个事件都有相应的状态代码 我编写了一些SQL来返回AT_设备中每个记录的最新事件代码。我有一个业务规则,如果设备没有记录事件,状态代码应该是0 在本例中,我编写的SQL查询返回0,但由于某些原因,它返回NULL。为什么? SELECT atDeviceHistory.StatusCodeNot

假设我有一个名为AT_Devices的SQL表,每个记录代表一个硬件。我还有一个名为AT_Event_History的表,它描述了硬件部件发生的“事件”。一个事件可以由诸如设备丢失、毁坏、报废等事件组成。每个事件都有相应的状态代码

我编写了一些SQL来返回AT_设备中每个记录的最新事件代码。我有一个业务规则,如果设备没有记录事件,状态代码应该是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

由于您正在执行
左联接
,如果没有匹配的记录,则引用
atDeviceHistory
列的任何内容都将返回空值。如果不希望返回不匹配的记录,请将其更改为
内部联接。我还建议将您的案例陈述更改为
合并

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

由于您正在执行
左联接
,如果没有匹配的记录,则引用
atDeviceHistory
列的任何内容都将返回空值。如果不希望返回不匹配的记录,请将其更改为
内部联接。我还建议将您的案例陈述更改为
合并

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
现在查询中出现了错误的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)
现在查询中出现了错误的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)

你能给我们看一些返回null的源数据吗?除非我遗漏了什么。您正在对派生表执行左外部联接。如果表
dbo.AT_Devices
中有派生表
atDeviceHistory
中不存在的行,那么结果集中的值将为空。为什么要这样做:CASE WHEN(StatusCode不为空),那么StatusCode ELSE 0 END而不是:ISNULL(StatusCode,0)?你能给我们看一些返回null的源数据吗?除非我遗漏了什么。您正在对派生表执行左外部联接。如果表
dbo.AT_Devices
中有派生表
atDeviceHistory
中不存在的行,那么结果集中的值将为空。为什么要这样做:当(StatusCode不为空)时,则StatusCode ELSE 0结束而不是:ISNULL(StatusCode,0)?+1:非常好!在这种特殊情况下,我需要使用
左外部联接
,因为在我的生产代码中还有其他字段被读取。但是,我仍然想让我的查询为该列返回一个默认值0,否则该列将为NULL。请尝试将合并放到顶层的select上,而不是子查询上。+1:非常好!在这种特殊情况下,我需要使用
左外部联接
,因为在我的生产代码中还有其他字段被读取。但是,我仍然希望让我的查询为此列返回一个默认值0,否则它将为NULL。请尝试将合并抛出到顶层的select上,而不是子查询上。