我有3个表,我想计算所有活动的串行资产。
我需要显示Serialized Inventory行,但可能没有将详细信息添加到SerialAssets表中,因此这给了我NULL行。 这样工作很好......
SELECT inv.Id AS Id, COUNT(s.Id) AS Total, MIN(i.Name) AS Asset
FROM SerialAssets AS s
RIGHT JOIN Inventories AS inv ON s.InventoryId = inv.Id
INNER JOIN Items AS i ON inv.ItemId = i.Id
WHERE i.Serialised = 1
GROUP BY inv.Id
但是现在我添加了软删除我只需要计算活动的SerialAssets,所以在WHERE中添加AND s.Active = 1可以正常工作,但它会删除通常显示为0的空值行。显然因为如果s .Active为null未选中,有没有办法更改计数或使s.active = 1或null?
更新
解决方案:
Damien_The_Unbeliever &安培; 的利芬
感谢您的快速回复!
答案 0 :(得分:3)
将AND s.Active = 1
添加到 join 条件中,而不是添加到where子句中:
SELECT inv.Id AS Id, COUNT(s.Id) AS Total, MIN(i.Name) AS Asset
FROM SerialAssets AS s
RIGHT JOIN Inventories AS inv ON s.InventoryId = inv.Id
AND s.Active = 1
INNER JOIN Items AS i ON inv.ItemId = i.Id
WHERE i.Serialised = 1
GROUP BY inv.Id
到(逻辑上)评估WHERE
子句时,它并不关心结果集中每列的来源是什么 - 它关心的是评估那些条件中的值的条件列。如果这些列包含NULL
,则它不知道是否因为该列在基表中包含NULL
,或者它是外部JOIN
不成功的结果。
答案 1 :(得分:1)
如果“活动”始终为1,0或null,则只能SUM
处于活动状态。
更通用的解决方案看起来像这样
SUM(CASE
WHEN /*insert active condition here*/ THEN 1
ELSE 0
END) AS ActiveCount
答案 2 :(得分:1)
将s.Active= 1
更改为
ISNULL(s.Active, 1) = 1
COALESCE(s.Active, 1) = 1
用指定的替换值替换NULL。
返回其参数中的第一个非空表达式。
答案 3 :(得分:0)
我可能没有遇到问题...但你是否试图计算所有s.Id等于1而不过滤查询返回的行?
如果是这种情况:
将count(s.Id)
替换为count(case when s.Id = 1 then 1 end)
答案 4 :(得分:0)
试试这个:
SELECT inv.Id AS Id,
SUM(CASE WHEN COALESCE(s.ACtive, 1) = 1 THEN 1 ELSE 0 END) AS Total,
MIN(i.Name) AS Asset
FROM Inventories AS inv
INNER JOIN Items AS i ON inv.ItemId = i.Id
LEFT OUTER JOIN SerialAssets AS s ON
inv.Id = s.InventoryId
WHERE i.Serialised = 1
GROUP BY inv.Id
我重新安排了您的查询。最好使用LEFT OUTER JOIN代替。通过LEFT JOIN,人们更容易理解并且SQL Server的执行速度更快。