Reputation: 3147
I have this query which returns Null, to show 0 i can use ISNULL on outer query around CAST, i don't know if it is better to use ISNULL in the inner query.
I have tried using ISNULL with inner query but it returns no rows instead of showing 0. I have tried removing group by clause but still same results.
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
I have simplified this query, thanks to @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';
Now would it be okay to use ISNULL like that?
ISNULL((SUM(case when a.PODeliveryDate <> '19001212' then 1.0 else 0.0 end) / COUNT(*)) * 100 as AssignWithPO,0)
Execution Plan of both queries
Upvotes: 1
Views: 303
Reputation: 1269445
You don't need the second level of subqueries. You can use conditional aggregation instead. I think the following will do what you want:
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;
I'm not 100% sure, because I don't understand the relationships between AssignmentId
, StaffId
, and CreatedDate
, but my assumption is that the rows counted for AssignWithPO
are subject to the same conditions as the TotalCount
.
You don't need the count(distinct)
because AssignmentId
is necessarily unique because of the group by
. Assuming there is no overlap between the values, you don't need the group by
either, nor the outer query:
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';
Upvotes: 1