Counting values within the same row in SQL Server - sql

My SQL Server problem is as follows: let's say we have clients and we wish to rate them based on 4 categories (Score_1...Score_4) on a scale of 0 to 2. I have a table presented below:
What I want my code to do is count the number of 0, 1, and 2 values each of my clients recieved. The result table I would like to get would like this:
So client_1 got two 0 scores, one 1 score and one 2 score, client_2 got one 0 score, one 1 score and two 2 scores. Any suggestions? Thanks in advance!

You can unpivot, then do conditional aggregation:
select t.id,
sum(case when x.score = 0 then 1 else 0 end) cnt_0,
sum(case when x.score = 1 then 1 else 0 end) cnt_1,
sum(case when x.score = 2 then 1 else 0 end) cnt_2
from mytable t
cross apply (values (score_1), (score_2), (score_3), (score_4)) x(score)
group by t.id

Related

Adding a dummy identifier to data that varies by position and value

I am working on a project in SQL Server with diagnosis codes and a patient can have up to 4 codes but not necessarily more than 1 and a patient cannot repeat a code more than once. However, codes can occur in any order. My goal is to be able to count how many times a Diagnosis code appears in total, as well as how often it appears in a set position.
My data currently resembles the following:
PtKey
Order #
Order Date
Diagnosis1
Diagnosis2
Diagnosis3
Diagnosis 4
345
1527
7/12/20
J44.9
R26.2
NULL
NULL
367
1679
7/12/20
R26.2
H27.2
G47.34
NULL
325
1700
7/12/20
G47.34
NULL
NULL
NULL
327
1710
7/12/20
I26.2
J44.9
G47.34
NULL
I would think the best approach would be to create a dummy column here that would match up the diagnosis by position. For example, Diagnosis 1 with A, and Diagnosis 2 with B, etc.
My current plan is to rollup the diagnosis using an unpivot:
UNPIVOT ( Diag for ColumnALL IN (Diagnosis1, Diagnosis2, Diagnosis3, Diagnosis4)) as unpvt
However, this still doesn’t provide a way to count the diagnoses by position on a sales order.
I want it to look like this:
Diagnosis
Total Count
Diag1 Count
Diag2 Count
Diag3 Count
Diag4 Count
J44.9
2
1
1
0
0
R26.2
1
1
0
0
0
H27.2
1
0
1
0
0
I26.2
1
1
0
0
0
G47.34
3
1
0
2
0
You can unpivot using apply and aggregate:
select v.diagnosis, count(*) as cnt,
sum(case when pos = 1 then 1 else 0 end) as pos_1,
sum(case when pos = 2 then 1 else 0 end) as pos_2,
sum(case when pos = 3 then 1 else 0 end) as pos_3,
sum(case when pos = 4 then 1 else 0 end) as pos_4
from data d cross apply
(values (diagnosis1, 1),
(diagnosis2, 2),
(diagnosis3, 3),
(diagnosis4, 4)
) v(diagnosis, pos)
where diagnosis is not null;
Another way is to use UNPIVOT to transform the columns into groupable entities:
SELECT Diagnosis, [Total Count] = COUNT(*),
[Diag1 Count] = SUM(CASE WHEN DiagGroup = N'Diagnosis1' THEN 1 ELSE 0 END),
[Diag2 Count] = SUM(CASE WHEN DiagGroup = N'Diagnosis2' THEN 1 ELSE 0 END),
[Diag3 Count] = SUM(CASE WHEN DiagGroup = N'Diagnosis3' THEN 1 ELSE 0 END),
[Diag4 Count] = SUM(CASE WHEN DiagGroup = N'Diagnosis4' THEN 1 ELSE 0 END)
FROM
(
SELECT * FROM #x UNPIVOT (Diagnosis FOR DiagGroup IN
([Diagnosis1],[Diagnosis2],[Diagnosis3],[Diagnosis4])) up
) AS x GROUP BY Diagnosis;
Example db<>fiddle
You can also manually unpivot via UNION before doing the conditional aggregation:
SELECT Diagnosis, COUNT(*) As Total Count
, SUM(CASE WHEN Position = 1 THEN 1 ELSE 0 END) As [Diag1 Count]
, SUM(CASE WHEN Position = 2 THEN 1 ELSE 0 END) As [Diag2 Count]
, SUM(CASE WHEN Position = 3 THEN 1 ELSE 0 END) As [Diag3 Count]
, SUM(CASE WHEN Position = 4 THEN 1 ELSE 0 END) As [Diag4 Count]
FROM
(
SELECT PtKey, Diagnosis1 As Diagnosis, 1 As Position
FROM [MyTable]
UNION ALL
SELECT PtKey, Diagnosis2 As Diagnosis, 2 As Position
FROM [MyTable]
WHERE Diagnosis2 IS NOT NULL
UNION ALL
SELECT PtKey, Diagnosis3 As Diagnosis, 3 As Position
FROM [MyTable]
WHERE Diagnosis3 IS NOT NULL
UNION ALL
SELECT PtKey, Diagnosis4 As Diagnosis, 4 As Position
FROM [MyTable]
WHERE Diagnosis4 IS NOT NULL
) d
GROUP BY Diagnosis
Borrowing Aaron's fiddle, to avoid needing to rebuild the schema from scratch, and we get this:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d1f7f525e175f0f066dd1749c49cc46d

SQL query issue COUNT()

I tried set the count of rows which have a specific value for multiple columns in the same query
this is what I have tried...
SELECT
COUNT(*) AS house_with_12_rooms,
COUNT(*) AS house_with_4_rooms
FROM housetable
WHERE num_of_rooms = "twelve"
OR num_of_rooms = "four"
since there are 157 rows with houses with 12 rooms and 1 row with houses with 4 rooms the result adds up the counts in the result table RATHER THAN placing 157 and 1 respectively.
Row house_with_12_rooms house_with_4_rooms
1 158 158
Could someone give me a clue on how to set up the query properly?
Use conditional aggregation:
SELECT SUM(CASE WHEN num_of_rooms = 'twelve' THEN 1 ELSE 0 END) AS house_with_12_rooms,
SUM(CASE WHEN num_of_rooms = 'four' THEN 1 ELSE 0 END) AS house_with_4_rooms
FROM housetable
WHERE num_of_rooms IN ('twelve', 'four')

conditional aggregation on two different groups in SQL

Here is my data
COUNTYID POLLUTANT TYPE EMISSION
1 A 1
1 A 2
1 B 1
1 B 2
2 A 1
2 A 2
2 B 1
2 B 2
3 A 1
3 A 2
3 B 1
3 B 2
if I do
SELECT sum(EMISSION) from table where POLLUTANT = 'A' group by COUNTYID;
I would get pollution from Polutant 'A'. how can I write a query to get following data:
column 1 with sum of A, column 2 with sum of B, column 3 with sum of A and B?
Thank you
You can use case for filter the value you need
select COUNTYID, sum(case when POLLUTANT='A'then EMISSION else 0 END) tot_a
, sum(case when POLLUTANT='B'then EMISSION else 0 END) tot_b
, sum(EMISSION) tot_a_b
from my_table
group by COUNTYID
You can use conditional aggregation. This moves the filtering conditions from the where clause to the sum()s:
select countyid,
sum(case when emission = 'A' then emission else 0 end) as A,
sum(case when emission = 'B' then emission else 0 end) as B,
sum(emission) as total
from t
group by countyid;
I would like to give some idea. We can use pivot table for answer your question
SELECT * from dbo.[Table_1]
PIVOT
(Sum([type_emmssion]) for [polutant] in ([A], [B]) ) as PivotTable
group by [CountryId] ;
you have to use case statemet:
SELECT
SUM( CASE WHEN POLLUTANT = 'A' THEN EMISSION ELSE 0 END) AS A_EMISSION
SUM( CASE WHEN POLLUTANT = 'B' THEN EMISSION ELSE 0 END) AS B_EMISSION
SUM(EMISSION) AS total_emission
FROM table
GROUP BY COUNTYID;

Running Counts on Multiple Columns with One SQL Query

I'm looking to run a count SQL query on multiple columns at once. 83 of them. For each, I'd simply like to figure out how many instances there are in which the value = 1.
ex.
select count(*) from [filename.filename]
where [Column001] = 1
select count(*) from [filename.filename]
where [Column002] = 1
All data in each column is marked with wither a 0 or a 1.
Instead of writing 83 small queries, is there a way for me to write it all in one query and have them all display as a table with the results?
This seems to be what you want:
SELECT SUM(CASE WHEN Column_1 = 1 THEN 1 ELSE 0 END) N_1,
SUM(CASE WHEN Column_2 = 1 THEN 1 ELSE 0 END) N_2,
SUM(CASE WHEN Column_3 = 1 THEN 1 ELSE 0 END) N_3,
.....
SUM(CASE WHEN Column_83 = 1 THEN 1 ELSE 0 END) N_83
FROM YourTable;

SQL Server : display column states by date

This is my db schema:
http://sqlfiddle.com/#!3/bbaea/3
The only important columns are CreationTime (as a timestamp) and Result.
Result can currently be 0, 1, 2 or 3
What my result should look like:
Year, Month, Day | Entries with Result 0 | With 1 | With 2 | ..
I'm new to SQL Server itself and I have no idea how to solve this problem. I tried some subselects (like in my fiddle) but they are not working as expected. I guess this is because I have to join the subselects, but how? Also I want to know the best way of how to do this..
Some help?
You don't need to union several queries. You can use a case statement:
SELECT
DAY(CreationTime) AS d, MONTH(CreationTime) AS m, YEAR(CreationTime) AS y
,count(CASE WHEN RESULT = 0 THEN 1 ELSE NULL END) AS R0
,count(CASE WHEN RESULT = 1 THEN 1 ELSE NULL END) AS R1
,count(CASE WHEN RESULT = 2 THEN 1 ELSE NULL END) AS R2
FROM History
GROUP BY DAY(CreationTime), MONTH(CreationTime), YEAR(CreationTime)
SELECT * FROM History;
Answer on SQL Fiddle.
You can try this
SELECT YEAR(CreationTime) AS y, MONTH(CreationTime) AS m, DAY(CreationTime) AS d,
COUNT(CASE WHEN Result = 0 THEN 1 END) AS WITH0,
COUNT(CASE WHEN Result = 1 THEN 1 END) AS WITH1,
COUNT(CASE WHEN Result = 2 THEN 1 END) AS WITH2
FROM History
GROUP BY YEAR(CreationTime), MONTH(CreationTime), DAY(CreationTime)