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