1

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

2 回答 2

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
于 2012-05-17T17:33:48.390 回答
0

既然@Abe Miessler 已经指出了查询中放错位置的 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)
于 2012-05-18T05:24:18.117 回答