Count Category From Column [duplicate] - sql-server

This question already has answers here:
Conditional Count on a field
(8 answers)
Closed last year.
I have some table, which I want count column that column have 2 category, the explain table like this:
I have query with union like this:
select CLASS, BRANCH, COUNT(STATUS) as STATUS
from dwh.Table a
where STATUS = 'INCLUDE'
group by CLASS, BRANCH, STATUS
order by CLASS
union
select CLASS, BRANCH, COUNT(STATUS) as STATUS
from dwh.Table a
where STATUS = 'NOT INCLUDE'
group by CLASS, BRANCH, STATUS
order by CLASS
but I have got some error.

I think you want conditional aggregation here:
SELECT
CLASS,
BRANCH,
COUNT(CASE WHEN STATUS = 'INCLUDE' THEN 1 END) AS [INCLUDE],
COUNT(CASE WHEN STATUS = 'NOT INCLUDE' THEN 1 END) AS [NOT INCLUDE]
FROM dwh.Table
GROUP BY
CLASS,
BRANCH;
If you just want to report classes only, then simply group by the class by itself (and also select only the class):
SELECT
CLASS,
COUNT(CASE WHEN STATUS = 'INCLUDE' THEN 1 END) AS [INCLUDE],
COUNT(CASE WHEN STATUS = 'NOT INCLUDE' THEN 1 END) AS [NOT INCLUDE]
FROM dwh.Table
GROUP BY
CLASS;

A simple group by and count can do that
select t.class,
count(case when t.status = 'INCLUDE' then 1 end) as INCLUDE,
count(case when t.status = 'NOT INCLUDE' then 1 end) as [NOT INCLUDE]
from test t
group by t.class
Test it yourself in this DBFiddle
That will leave a warning though
Warning: Null value is eliminated by an aggregate or other SET
operation.
So another way to do it is group by and sum and this way you will not get a warning anymore
select t.class,
sum(case when t.status = 'INCLUDE' then 1 else 0 end),
sum(case when t.status = 'NOT INCLUDE' then 1 else 0 end)
from test t
group by t.class
See the altered DBFiddle

Related

How can I combine the below 2 sql queries when there are multiple case statements with SUM involved

This is the first sub-query:
SELECT SUM(CASE WHEN TRADE_TYPE='SELL' THEN (QUANTITY*PRICE) END) -
SUM(CASE WHEN TRADE_TYPE='BUY' THEN (QUANTITY*PRICE) END) AS NET_PL, TRADINGSYMBOL AS STOCK_NAME
FROM dbo.[Table1]
GROUP BY TRADINGSYMBOL, TRADE_DATE
This is the second sub-query:
SELECT SUM(CASE WHEN TRADE_TYPE='BUY' THEN QUANTITY END) -
SUM(CASE WHEN TRADE_TYPE='SELL' THEN QUANTITY END) AS NET_QUANTITY, TRADINGSYMBOL AS STOCK_NAME
FROM dbo.[Table1]
GROUP BY TRADINGSYMBOL
This is the query result of second sub-query:
NET_QUANTITY STOCK_NAME
---------------------- --------------------------------------------------
NULL ABCL
0 ADAT
NULL BAF
NULL BEGE
0 CRECC
NULL CIEN
NULL DFMXA
NULL DFJL
-50 HDANK
1000 MEHD
NULL PRAK
0 TNTS
Every TRADINGSYMBOL that exists as part of second query result WITH NET QUANTITY 0 has to be combined/merged with the first query result. I mean apart from TRADINGSYMBOL(s) included in query-1, the query-2 TRADING SYMBOLS also have to get calculated for their (QUANTITY*PRICE) and should be part of final output.
Please guide me. Thank you.
A quick and easy way would be to just treat them as two sub-queries.
SELECT
PL.STOCK_NAME
,PL.NET_PL
,Q.NET_QUANTITY
FROM
(SELECT SUM(CASE WHEN TRADE_TYPE='SELL' THEN (QUANTITY*PRICE) END) -
SUM(CASE WHEN TRADE_TYPE='BUY' THEN (QUANTITY*PRICE) END) AS NET_PL, TRADINGSYMBOL AS STOCK_NAME
FROM dbo.[Table1]
GROUP BY TRADINGSYMBOL, TRADE_DATE) AS PL
FULL OUTER JOIN
(SELECT SUM(CASE WHEN TRADE_TYPE='BUY' THEN QUANTITY END) -
SUM(CASE WHEN TRADE_TYPE='SELL' THEN QUANTITY END) AS NET_QUANTITY, TRADINGSYMBOL AS STOCK_NAME
FROM dbo.[Table1]
GROUP BY TRADINGSYMBOL) AS Q ON PL.STOCK_NAME = Q.STOCK_NAME

Distinct Count when using Case When

I am having trouble getting the correct distinct count when using case when and distinct in SQL Server.
I have a column for count(distinct TA_STUDENT_ID) which calculates the correct count. I then have 2 additional columns in which I am doing a count by TA_LOCATION and the totals for the numbers on each row under TA_LOCATION need to add up to the COUNT of the DISTINCT TA_STUDENT_ID. I need help to get it to do that. Here is my query:
SELECT
count (distinct TA_STUDENT_ID) as 'count',
COUNT (CASE WHEN (TA_LOCATION = 'CCC') THEN 'CCC' END) AS 'CCC',
COUNT(CASE WHEN (TA_LOCATION = 'SCCDC') THEN 'SCCDC' END) AS 'SCCDC',
[TA_AW_ID]
FROM [S85_TA_ACYR]
group by [TA_AW_ID]
order by [TA_AW_ID]
My desired results are that the totals on each row in the TA_LOCATION columns should total and match the numbers on the rows in my COUNT DISTINCT TA_STUDENT_ID column.
Use DISTINCT inside COUNT() with CASE expression :
SELECT COUNT(DISTINCT TA_STUDENT_ID) as 'count',
COUNT(DISTINCT CASE WHEN (TA_LOCATION = 'CCC') THEN TA_STUDENT_ID END) AS 'CCC',
COUNT(DISTINCT CASE WHEN (TA_LOCATION = 'SCCDC') THEN TA_STUDENT_ID END) AS 'SCCDC',
[TA_AW_ID]
FROM [S85_TA_ACYR]
GROUP BY [TA_AW_ID]
ORDER BY [TA_AW_ID];
You can also use a SUM() for the second two fields, like this:
SELECT
Count = COUNT(DISTINCT TA_STUDENT_ID)
,CCC = SUM(CASE WHEN ( TA_LOCATION = 'CCC' ) THEN 1 ELSE 0 END)
,SCCDC = SUM(CASE WHEN ( TA_LOCATION = 'SCCDC' ) THEN 1 ELSE 0 END)
,TA_AW_ID
FROM S85_TA_ACYR
GROUP BY TA_AW_ID
ORDER BY TA_AW_ID

SQL sum of current year commissions is higher than previous year

Trying to compare sum of current year commissions to the previous year but having trouble creating an inner join. If thisYear is higher I will update a growth_incentive field to '.05' Currently have something like this that gets the data but I feel like its inefficient
SELECT a.emp_no, SUM(a.total_commission) AS ThisYearComm
,(select SUM(total_commission) AS LastYearComm
from tbl_comm_medmon_employees_stats
where emp_no = a.emp_no
and year(getdate())-1 = comm_year) as lastyear
FROM tbl_comm_medmon_employees_stats a
where year(getdate()) = a.comm_year
GROUP BY a.emp_no, a.comm_year
If I understand your table correctly, you don't need a join. Try using conditional aggregation instead, like this:
SELECT a.emp_no
, SUM(case when year(getdate()) = a.comm_year then a.total_commission end) AS ThisYearComm
, SUM(case when year(getdate()) - 1 = a.comm_year then a.total_commission end) AS LastYearComm
FROM tbl_comm_medmon_employees_stats a
where a.comm_year in (year(getdate()), year(getdate()) - 1)
GROUP BY a.emp_no
You could try to use a conditional SUM instead
SELECT a.emp_no,
SUM(CASE WHEN year(getdate())-1 = a.comm_year THEN a.total_commission
ELSE 0
END) [LastYear],
SUM(CASE WHEN year(getdate()) = a.comm_year THEN a.total_commission
ELSE 0
END) [ThisYearComm]
FROM tbl_comm_medmon_employees_stats a
GROUP BY a.emp_no

SQL Joins : in, out, shake it all about

I am performing the follwing sql to return a data where there is a match of both dob and address in tables1 & 2.
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count'
from table1
inner join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > #myDate
group by table1.dob, table1.address
order by table1.dob, table1.address
However I now want to return the data from table1 when there is no match in table2 and only that data, I thought simply changing inner join to left outer would perform what I required, it does not.
Thanks!
If there is no match in the join, the field from the second table are NULL, so you have to check for a NULL value in table2. Assuming dob is NOT NULL in table2, this should solve your problem:
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count'
from table1
left outer join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > #myDate and table2.dob is null
group by table1.dob, table1.address
order by table1.dob, table1.address
In this case thre's not a join, you should use NOT EXISTS function.
In my opinion LEFT JOIN is much more cleaner and you should go with that if there is no big difference between the performance of LEFT JOIN and NOT EXISTS. #JNK said "EXISTS and NOT EXISTS are ordinarily faster than joins or other operators like IN because they short circuit - the first time they get a hit they move on to the next entry", but my understanding is that NOT EXISTS and NOT IN are usually expensive as sql server has to go through all the records in the lookup table to make sure that the entry in fact does NOT EXIST, so i dont know how the short circuit would work
You could also use the EXCEPT keyword here.
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count'
from table1
where table1.dob > #myDate
EXCEPT
select table1.dob
, table1.address
, sum(case when person_status in ('A','B','C') then 1 else 0 end) as 'ABC_count'
, sum(case when person_status in ('D','E') then 1 else 0 end) as 'DE_Count'
, sum(case when person_status in ('F','G') then 1 else 0 end) as 'FG_Count'
from table1
inner join table2
on (table1.dob = table2.dob and table1.address = table2.address)
where table1.dob > #myDate
That would get you all of the records in the first query that are not in the second query.

Help with finding the difference (delta) from a value returned from the last two records

I'm using MS SQL 2005 and I have created a CTE query to return values from the last two records. I then use this to find the delta of two figures returned. I have a working query of sorts but
I'm having problems getting anything other than the delta figure.
here is my query:
;with data as(
SELECT
NetObjectID,
RawStatus,
RowID,
rn
from(
SELECT
CustomPollerAssignmentID AS NetObjectID,
RawStatus,
RowID,
row_number() over(order by DateTime desc)as rn
FROM CustomPollerStatistics_Detail
WHERE
(CustomPollerAssignmentID='a87f531d-4842-4bb3-9d68-7fd118004356')
) x where rn<=2
)
SELECT
case when
max(case rn when 1 then RawStatus end) > max(case rn when 2 then RawStatus end)
then
max(case rn when 1 then RawStatus end) - max(case rn when 2 then RawStatus end)
else
max(case rn when 2 then RawStatus end) - max(case rn when 1 then RawStatus end)
end as Delta
from data having
(SELECT
case when
max(case rn when 1 then RawStatus end) > max(case rn when 2 then RawStatus end)
then
max(case rn when 1 then RawStatus end) - max(case rn when 2 then RawStatus end)
else
max(case rn when 2 then RawStatus end) - max(case rn when 1 then RawStatus end)
end
from data) >= 1
What I'm after is to get the Delta & NetObjectID returned. Each time I try, I get errors.
data.NetObjectID is invalid in the select list because it is not contained in either an aggregate function or the group by clause.
If I try adding group by etc.. to the end of the query I get further error complaining about the word 'group'.
I'm relatively new to SQL and I am picking things up as I go. Any help would be gratefully received.
see if something like this will work.
;with data as
(
SELECT
NetObjectID,
RawStatus,
RowID,
rn
from
(
SELECT
CustomPollerAssignmentID AS NetObjectID,
RawStatus,
RowID,
row_number() over(order by DateTime desc)as rn
FROM CustomPollerStatistics_Detail
WHERE
(
CustomPollerAssignmentID='a87f531d-4842-4bb3-9d68-7fd118004356'
)
) x
where rn<=2
)
select
NetObjectID,
max(RawStatus)-min(RawStatus) as Delta
from data
group by NetObjectID
Sorry, I'm very new here and I'm unsure of CTE queries, however it looks like after you define Data, you are selecting case ... as Delta FROM.... Meaning you only have Delta in your select statement. Again, sorry if I'm way off base.

Resources