没有返回行时返回0

时间:2014-03-11 16:06:54

标签: sql sql-server-2008

我有这个返回Null的查询,显示0我可以在CAST周围的外部查询上使用ISNULL,我不知道在内部查询中使用ISNULL是否更好。

我尝试过使用带有内部查询的ISNULL,但它没有返回任何行而不是显示0.我尝试删除group by子句,但结果仍然相同。

SELECT CAST((SUM(q.AssingWithPO * 1.0) / SUM(q.TotalAssign * 1.0)) * 100
                                                                 AS NUMERIC (10,2))
FROM
(
  SELECT COUNT(DISTINCT a.AssignmentID) AS TotalAssign
    ,(SELECT COUNT(DISTINCT a2.AssignmentID)FROM Assignments a2
       WHERE a2.PODeliveryDate <> '19001212'
        AND a2.AssignmentID = a.AssignmentID ) AS AssingWithPO

  FROM Assignments a
  WHERE a.StaffID = 59
  AND (a.CreatedDate BETWEEN '20130101' AND '20141231')
  GROUP BY a.AssignmentID
)q;

ADDED

由于@Gordon

,我简化了这个查询
SELECT SUM(case when a.PODeliveryDate <> '19001212' then 1.0 else 0.0 end) / COUNT(*)) * 100 as AssignWithPO
 FROM Assignments a
 WHERE a.StaffID = 59 AND
       a.CreatedDate BETWEEN '20130101' AND '20141231';

现在可以像这样使用ISNULL吗?

ISNULL((SUM(a.PODeliveryDate&lt;&gt;'19001212'然后1.0,否则0.0结束)/ COUNT(*))* 100作为AssignWithPO,0)

两个查询的执行计划

enter image description here

1 个答案:

答案 0 :(得分:1)

您不需要第二级子查询。您可以改为使用条件聚合。我认为以下内容可以满足您的需求:

SELECT CAST((SUM(a.AssignWithPO * 1.0) / SUM(a.TotalAssign * 1.0)) * 100 as NUMERIC (10,2))
FROM (SELECT COUNT(*) AS TotalAssign,
             SUM(case when a.PODeliveryDate <> '19001212' then 1 else 0 end) as AssignWithPO
     FROM Assignments a
     WHERE a.StaffID = 59 AND
           a.CreatedDate BETWEEN '20130101' AND '20141231'
     GROUP BY a.AssignmentID
    ) a;

我不是百分百肯定,因为我不理解AssignmentIdStaffIdCreatedDate之间的关系,但我的假设是行AssignWithPO计算的条件与TotalCount相同。

您不需要count(distinct),因为AssignmentIdgroup by而必然是唯一的。假设值之间没有重叠,您也不需要group by,也不需要外部查询:

     SELECT COUNT(*) AS TotalAssign,
            SUM(case when a.PODeliveryDate <> '19001212' then 1.0 else 0.0 end) / COUNT(*) as AssignWithPO
     FROM Assignments a
     WHERE a.StaffID = 59 AND
           a.CreatedDate BETWEEN '20130101' AND '20141231';