case statement doesn't go to else - sql

I am wondering why the following query doesn't give 'N/A' when there are no rows for ENVIRON='Dev/Int'. It is returning null in the result of the query. I tried doing NVL(COUNT(*)) but that does't work either.
Any thoughts?
Thanks in advance.
SELECT G1.NAME,
(SELECT CASE
WHEN COUNT(*) > 0 AND ticket IS NOT NULL THEN 'Solved'
WHEN COUNT(*) > 0 AND ticket IS NULL THEN 'Done'
ELSE 'N/A'
END
FROM TABLE1
WHERE ENVIRON='Dev/Int' AND G1.NAME=NAME GROUP BY ENVIRON, ticket ) "Dev/Int"
FROM TABLE1 G1 group by G1.NAME

It doesn't give any rows because you are filtering them all out. The case is inside the query. When there are no rows to process, it returns NULL.
I think you just want conditional aggregation. The subqueries don't seem necessary:
SELECT G1.NAME,
(CASE WHEN SUM(CASE WHEN ENVIRON = 'Dev/Int' then 1 else 0 END) > 0 AND ticket IS NOT NULL
THEN 'Solved'
WHEN SUM(CASE WHEN ENVIRON = 'Dev/Int' then 1 else 0 END) > 0 AND ticket IS NULL
THEN 'Done'
ELSE 'N/A'
END) as "Dev/Int"
FROM TABLE1
group by G1.NAME;
EDIT:
Oops, the above left ticket out of the sum(). I think the logic you want has ticket in the sum() condition:
SELECT G1.NAME,
(CASE WHEN SUM(CASE WHEN ENVIRON = 'Dev/Int' AND ticket IS NOT NULL then 1 else 0 END) > 0
THEN 'Solved'
WHEN SUM(CASE WHEN ENVIRON = 'Dev/Int' AND ticket IS NULL then 1 else 0 END) > 0
THEN 'Done'
ELSE 'N/A'
END) as "Dev/Int"
FROM TABLE1
group by G1.NAME;
I'm surprised your original query worked at all and didn't get an error of the sort that subquery returned more than one row.

Related

Remove duplicates records from sum statement using SQL server

Hi i have a table in which it has some duplicate records i want to remove all duplicate records and get the total count for that condition . I have tried following query here in first query it will include duplicate records also .
1> select count(fd.FarmerRegNo) as TotalRecord,
sum(case when fd.TSStatus='Approved' and Status!=0 then 1 else 0 end) Approved,
sum(case when fd.TSStatus='Pending' and fd.Status=0 then 1 else 0 end) Pending,
from FarmerDetail as fd
2> select count(distinct FarmerRegNo) as [Approved] from FarmerDetail where TSStatus='Approved'
see the image i want to get the 2nd table value in first table approved column how to remove duplicates for this condition
Is this what you want?
select
count(distinct fd.FarmerRegNo) as TotalRecord,
count(distinct case when fd.TSStatus = 'Approved' and Status != 0 then fd.FarmerRegNo end) Approved,
count(distinct case when fd.TSStatus = 'Pending' and Status = 0 then fd.FarmerRegNoend) Pending,
from FarmerDetail as fd
Use a conditional count(distinct):
select count(fd.FarmerRegNo) as TotalRecord,
count(distinct case when fd.TSStatus = 'Approved' and fd.Status <> 0 then fd.FarmerRegNo end) as Approved,
count(distinct case when fd.TSStatus = 'Pending' and fd.Status = 0 then fd.FarmerRegNo end) as Pending,
from FarmerDetail fd ;
Use the below query with sub query
select count(fd.FarmerRegNo) as TotalRecord,
(select count(distinct FarmerRegNo) from FarmerDetail where TSStatus='Approved') as Approved,
sum(case when fd.TSStatus='Pending' and fd.Status=0 then 1 else 0 end) Pending,
from FarmerDetail as fd

How to aggregate unioned tables with count and dummy values?

I am counting in two tables some stuff and want one aggregated result (one row). I write this SQL for this purpose:
SELECT sum (Amount_New) Amount_New,
sum(Import_Dropout) Import_Dropout,
sum(Import)Import,
sum(Processing)Processing,
sum(Processing_Dropout)Processing_Dropout,
sum(Matching)Matching,
sum(Matching_Dropout)Matching_Dropout,
sum(Export)Export,
sum(Exported)Exported,
sum(Rejected)Rejected,
sum(AmountSubTotal)AmountSubTotal,
sum(AmountTotal)AmountTotal
FROM (
SELECT COUNT(CASE WHEN ProcessStatus='_New' THEN 1 ELSE null END) AS Amount_New,
COUNT(CASE WHEN ProcessStatus='Import_Dropout' THEN 1 ELSE null END) AS Import_Dropout,
COUNT(CASE WHEN ProcessStatus='Import' THEN 1 ELSE null END) AS Import,
COUNT(CASE WHEN ProcessStatus='Processing' THEN 1 ELSE null END) AS Processing,
COUNT(*) AS AmountTotal,
0 as Processing_Dropout,
0 as Matching,
0 as Matching_Dropout,
0 as Export,
0 as Export_Dropout,
0 as Exported,
0 as Rejected,
0 as AmountSubTotal,
0 as UnionOrder
FROM "fileimport$marketscanimportcsv"
WHERE ft_boekdat like '%2018%'
UNION
SELECT 0 AS Amount_New,
0 AS Import_Dropout,
0 AS Import,
COUNT(CASE WHEN ProcessStatus='Processing_Dropout' THEN 1 ELSE null END) AS Processing_Dropout,
COUNT(CASE WHEN ProcessStatus='Processing' THEN 1 ELSE null END) AS Processing,
COUNT(CASE WHEN ProcessStatus='Matching' THEN 1 ELSE null END) AS Matching,
COUNT(CASE WHEN ProcessStatus='Matching_Dropout' THEN 1 ELSE null END) AS Matching_Dropout,
COUNT(CASE WHEN ProcessStatus='Export' THEN 1 ELSE null END) AS Export,
COUNT(CASE WHEN ProcessStatus='Export_Dropout' THEN 1 ELSE null END) AS Export_Dropout,
COUNT(CASE WHEN ProcessStatus='Exported' THEN 1 ELSE null END) AS Exported,
COUNT(CASE WHEN ProcessStatus='Rejected' THEN 1 ELSE null END) AS Rejected,
COUNT(CASE WHEN ProcessStatus!= '_New' and ProcessStatus!= 'Import_Dropout' and ProcessStatus!= 'Import' THEN 1 ELSE null END) AS AmountSubTotal,
COUNT(*) AS AmountTotal,
1 as UnionOrder
FROM "matching$marketscanmovement"
WHERE date_part ('year', BookingDate_BA_MS)= 2018
) SK GROUP by unionorder order by unionorder asc
1) The result is 2 rows, which is not one value as total of that column.
Why is this query not summarizing the unioned same column values? How should it be written?
2) When I try sum "(Amount_New1+Amount_New2) Amount_New" (and changing the subquery column names to amount_new1 / amount_new2) it is not working neither. Why?
If you want to return a single row, conceptually representing an aggregate over the entire union table, then remove GROUP BY:
SELECT SUM(Amount_New) Amount_New,
SUM(Import_Dropout) Import_Dropout,
SUM(Import) Import,
SUM(Processing) Processing,
SUM(Processing_Dropout) Processing_Dropout,
SUM(Matching) Matching,
SUM(Matching_Dropout) Matching_Dropout,
SUM(Export) Export,
SUM(Exported) Exported,
SUM(Rejected) Rejected,
SUM(AmountSubTotal) AmountSubTotal,
SUM(AmountTotal) AmountTotal
FROM
(
-- ... your current query
) SK;
You also may want to remove the UnionOrder computed column, since there is no need to sort a single row result set.

Don't understand query behaviour

I have a strange behaviour in report builder.
I'm working from an existing dataset and testing my own code in SQL studio before trying in report builder. And I'm lost because I don't understand why the following doesn't work :
SELECT
v_Collection_Alias.Name as CollectionName,
v_Package_Alias.Name as SoftwareName,
'Package' as ApplicationType,
NumberSuccessTable='NumberSuccessTable', sum(case when stat.LastState in (-1,13) then 1 else 0 end) as NumberSuccess,
NumberInProgressTable='NumberInProgress', sum(case when stat.LastState in (8,9) then 1 else 0 end) as NumberInProgress,
NumberUnknownTable='NumberUnknown', sum(case when stat.LastState in (0) then 1 else 0 end) as Unknown,
NumberErrorTable='NumberError', sum(case when stat.LastState in (11) then 1 else 0 end) as NumberError,
NumberOtherTable='NumberOther', sum(case when stat.LastState in (10) then 1 else 0 end) as NumberOther,
'' as LastModifiedby,
'' as Version,
v_Advertisement_Alias.CollectionID as CollectionID,
v_Advertisement_Alias.AdvertisementID as DeploymentID,
'' as CI_ID,
'' as DeploymentTime,
v_Advertisement_Alias.PresentTime as ModificationTime,
'' as AssignmentID
FROM fn_rbac_Advertisement(#UserSIDs) v_Advertisement_Alias
JOIN fn_rbac_ClientAdvertisementStatus(#UserSIDs) stat on v_Advertisement_Alias.AdvertisementID = stat.AdvertisementID
INNER JOIN fn_rbac_Package2(#UserSIDs) v_Package_Alias ON v_Advertisement_Alias.PackageID = v_Package_Alias.PackageID
INNER JOIN fn_rbac_Collection(#UserSIDs) v_Collection_Alias ON v_Advertisement_Alias.CollectionID = v_Collection_Alias.CollectionID
This in report builder is prompting me an error because fn_rbac_Advertisement.Name need a group by clause. Whereas the following is properly working in the original report :
SELECT
v_Collection_Alias.Name as CollectionName,
v_Package_Alias.Name as SoftwareName,
'' as ApplicationType,
'' as NumberSuccess,
'' as NumberInProgress,
'' as NumberUnknown,
'' as NumberErrors,
'' as NumberOther,
'' as LastModifiedby,
'' as Version,
v_Advertisement_Alias.CollectionID as CollectionID,
v_Advertisement_Alias.AdvertisementID as DeploymentID,
'' as CI_ID,
'' as DeploymentTime,
v_Advertisement_Alias.PresentTime as ModificationTime,
'' as AssignmentID,
'' as ApplicationType
FROM fn_rbac_Advertisement(#UserSIDs) v_Advertisement_Alias
INNER JOIN fn_rbac_Package2(#UserSIDs) v_Package_Alias ON v_Advertisement_Alias.PackageID = v_Package_Alias.PackageID
INNER JOIN fn_rbac_Collection(#UserSIDs) v_Collection_Alias ON v_Advertisement_Alias.CollectionID = v_Collection_Alias.CollectionID
and the following returns me what I want in SQL Studio :
Select
NumberSuccessTable='NumberSuccessTable', sum(case when stat.LastState in (-1,13) then 1 else 0 end),
NumberInProgressTable='NumberInProgress', sum(case when stat.LastState in (8,9) then 1 else 0 end),
NumberUnknownTable='NumberUnknown', sum(case when stat.LastState in (0) then 1 else 0 end) AS NumberU,
NumberErrorTable='NumberError', sum(case when stat.LastState in (11) then 1 else 0 end) AS NumberError,
NumberOtherTable='NumberOther', sum(case when stat.LastState in (10) then 1 else 0 end) as NumberOther
From v_ClientAdvertisementStatus stat
Thanks for any help guys ! :)
First Query:
when you use aggregate function like SUM you need to do a GROUP BY on all your columns that Don't have the aggregate function.
Second Query:
this works because you dont have an aggregate function in your select therefor you dont have to use GROUP BY and report builder can handle the sum and group by for you.
Third query:
this query works because you have aggregate function on all your columns so you dont need to GROUP BY.
Always remember the LOGICAL query processing order is as below:
1.FROM
2.WHERE
3.GROUP BY
4.HAVING
5.SELECT
6.ORDER BY
so your GROUP BY happens before SELECT for that reason when you group by you cant include '' in your group by clause because that column does not exists yet.
so it gives you an error.
When using aggregate functions (such as SUM) you must apply a GROUP BY clause to all columns that are not aggregated eg:
GROUP BY v_Collection_Alias.Name,
v_Package_Alias.Name,
v_Advertisement_Alias.CollectionID as CollectionID,
v_Advertisement_Alias.AdvertisementID as DeploymentID,
v_Advertisement_Alias.PresentTime as ModificationTime
Alternatively, if you don't want to maintain a lengthy GROUP BY clause you could remove the SUM functions from the SELECT statement and let the report handle the aggregation, with appropriate grouping in Report Builder.

select query result filter using if conditions

I have folllowing select query
SELECT
Table.ID
SUM(CASE WHEN Table.Status = 1 THEN 1 ELSE null END) AS NormalCount,
SUM(CASE WHEN Table.status = 2 THEN 1 ELSE null END) AS AbnormalCount
FROM Table
GROUP BY Table.ID
I want to get above results and generate new result set with following conditions
IF(NormalCount > 0 or AbnormalCount == NULL)
SELECT
Table.ID
Table.Status AS "Normal"
FROM Table
GROUP BY Table.ID
ELSE IF ( AbnormalCount > 0)
SELECT
Table.ID
Table.Status AS "Abnormal"
SUM(CASE WHEN Header.status = 2 THEN 1 ELSE null END) AS AbnormalCount
FROM Table
GROUP BY Table.ID
I think the logic you want is to label each ID group as being abnormal if it has one or more abnormal observation. If so, then you can use another CASE statement to check the conditional abnormal sum and label the status appropriately. Normal groups would have the characteristic of having an abnormal count of zero, but this count would appear for all groups.
SELECT t.ID,
CASE WHEN SUM(CASE WHEN t.status = 2 THEN 1 ELSE 0 END) > 0
THEN "Abnormal"
ELSE "Normal" END AS Status,
SUM(CASE WHEN t.status = 2 THEN 1 ELSE 0 END) AS AbnormalCount
FROM Table t
GROUP BY t.ID

SQL to Return 0 instead of NULL

Trying to return 0 instead of NULL in the following select without success:
SELECT
IsNull(CASE WHEN TICKET IS NOT NULL THEN 1 ELSE 0 END,0) AS TICKET
FROM
TICKETS
WHERE
TICKET = '2'
Any suggestions? Thanks.
After reviewing the answers and your answer to them, I think what you want is: If no data returned, select 0 else select 1.. so:
SELECT case when exists(select 1 from tickets where ticket = '2')
then 1 else 0 end as IND
Use the CASE expression:
SELECT (CASE WHEN TICKET IS NOT NULL THEN 1 ELSE 0 END) AS TICKET
FROM TICKETS
WHERE TICKET = '2'
However, it makes no sense, because the value cannot be NULL given the WHERE clause. So, you can just do:
SELECT 1
FROM TICKETS
WHERE TICKET = '2';