Reputation: 47
I am trying to create a SQL statement that returns multiple counts. The count below works as I expect, but the case statement is ignoring the where clause for my query.
I'm trying to get the total number of PacketId's that meet the where criteria. Then get a second total showing the sum of PacketId's that meet the where criteria and have a StatusId of 3.
*edit Table1 and Table2 both share PacketId as a foreign key.
Select
Count(Distinct wpq.PacketId) AS Total,
SUM(Case When wpq.StatusId = 3 THEN 1 ELSE 0 END) as OtherCount
FROM [Table1] ppo JOIN [Table2] wpq ON ppo.PacketId = wpq.PacketId
WHERE wpq.CreateDate between '11/1/2017' and '1/1/2018' and ppo.IsSelected = 1
Upvotes: 1
Views: 474
Reputation: 35583
I suspect you may be getting a higher number than expected for the othercount
but that may be due to the use of count(distinct...)
which reduces the first column result, but not the second. Perhaps introducing a subquery to select only distinct values would help?
SELECT DISTINCT
wpq.PacketId
, wpq.StatusId
FROM [Table1] ppo
JOIN [Table2] wpq ON ppo.PacketId = wpq.PacketId
WHERE wpq.CreateDate BETWEEN '11/1/2017' AND '1/1/2018'
AND ppo.IsSelected = 1
;
then count from that, e.g:
SELECT
COUNT(PacketId) AS total
, COUNT(CASE WHEN StatusId = 3 THEN StatusId END) AS othercount
, SUM(CASE WHEN StatusId = 3 THEN 1 ELSE 0 END) AS othersum
FROM (
SELECT DISTINCT
wpq.PacketId
, wpq.StatusId
FROM [Table1] ppo
JOIN [Table2] wpq ON ppo.PacketId = wpq.PacketId
WHERE wpq.CreateDate BETWEEN '11/1/2017' AND '1/1/2018'
AND ppo.IsSelected = 1
) AS d
;
Note: the COUNT()
function ignores nulls, so I have added an alternative calculation method to consider. I prefer to use COUNT()
in such a query.
Also I would like to note that your use of what appears to be M/D/YYYY date literals is NOT safe. The safest date literal format in T-SQL is YYYYMMDD. Similarly using between is not best practice for date ranges and wpuld encourage you to use >=
and <
instead, like so:
SELECT
COUNT(PacketId) AS total
, COUNT(CASE WHEN StatusId = 3 THEN StatusId END) AS othercount
, SUM(CASE WHEN StatusId = 3 THEN 1 ELSE 0 END) AS othersum
FROM (
SELECT DISTINCT
wpq.PacketId
, wpq.StatusId
FROM [Table1] ppo
JOIN [Table2] wpq ON ppo.PacketId = wpq.PacketId
WHERE wpq.CreateDate >= '20171101' AND wpq.CreateDate < '20180101'
AND ppo.IsSelected = 1
) AS d
;
Note I'm not sure if you do want to include 1/1/2018, if you do then use < '20180102'
instead
Upvotes: 1
Reputation: 1269873
I would suggest that you use standard date formats. Most databases support YYYY-MM-DD:
SELECT COUNT(DISTINCT wpq.PacketId) AS Total,
SUM(Case When wpq.StatusId = 3 THEN 1 ELSE 0 END) as OtherCount
FROM [Table1] ppo JOIN
[Table2] wpq
ON ppo.PacketId = wpq.PacketId
WHERE wpq.CreateDate >= '2017-11-01' AND
wpq.CreateDate <= '2018-01-01' AND
ppo.IsSelected = 1;
It is possible that the date comparisons are really being done as strings, so they do not do what you expect.
Upvotes: 0