How do I query a table in SQL to produce a result where column names are stacked vertically based on a condition? - sql

Suppose I have a SQL table titled Users with the following example data:
Description Days
--------------------------
Healthy 10
High-blood pressure 20
Cholesterol 23
Diabetes 31
High-blood pressure 8
Healthy 12
Diabetes 18
Cholesterol 25
High-blood pressure 20
Healthy 6
How would I produce a result that looks like the following where the columns: Less_than_20_days, 20_days and Greater_than_20_days contains counts from the table above
Description Less_than_20_days 20_days Greater_than_20_days
-----------------------------------------------------------------------------------
Healthy 3 0 0
High-blood pressure 1 2 0
Cholesterol 0 0 2
Diabetes 1 0 1
I'm trying to get this to work in SQL Server and have tried using the union operator, temp tables and ctes but I can't seem to get the desired result.
Any help would be much appreciated!

You can combine case with sum():
select
[Description]
,sum(case when [Days] < 20 then 1 else 0 end) as Less_than_20_days
,sum(case when [Days] = 20 then 1 else 0 end) as d20_days
,sum(case when [Days] > 20 then 1 else 0 end) as Greater_than_20_days
from users
group by [Description]

Use conditional aggregation:
select description,
sum(case when days < 20 then 1 else 0 end) as num_lt_20,
sum(case when days = 20 then 1 else 0 end) as num_eq_20,
sum(case when days > 20 then 1 else 0 end) as num_gt_20
from t
group by description

Related

how to sum with case with oracle sql

I m having data in columns as:
item_id
month_in
amount
1
1
1500
1
1
1000
2
1
2500
3
1
2600
3
1
1000
4
1
2700
4
1
1000
1
2
1500
1
2
2000
2
2
1000
3
3
2500
3
3
2500
4
3
1000
4
3
2500
I want to have like this result
item_id
januari
februari
maret
1
2500
3500
0
2
2500
1000
0
3
3600
0
0
4
3700
0
3500
in oracle sql query how to solve this.
please help me
I have try this
select
item_id,
(case month_in=1 then sum(amout) end) AS januari
from table
group by item_id, month_in
order by item_id asc
but not working as I expected
We can try a pivot query here:
SELECT
item_id,
SUM(CASE WHEN month_in = 1 THEN amount ELSE 0 END) AS januari,
SUM(CASE WHEN month_in = 2 THEN amount ELSE 0 END) AS februari,
SUM(CASE WHEN month_in = 3 THEN amount ELSE 0 END) AS maret
FROM yourTable
GROUP BY
item_id
ORDER BY
item_id;
You almost got it. This is the simplest solution, without extra hassle:
SELECT
item_id,
SUM(CASE WHEN month_in = 1 THEN amount ELSE 0 END) AS januari,
SUM(CASE WHEN month_in = 2 THEN amount ELSE 0 END) AS februari,
SUM(CASE WHEN month_in = 3 THEN amount ELSE 0 END) AS maret
from table
group by item_id
order by item_id asc
You don't need to define the months as a separate rowset, because the months are defined as values 1, 2, 3, ... as columns. Similarly, the items are defined by the group by function.

Create a score card report based on match results in SQL

Here's my sample input of match results from a tournament and the result column indicates whether team 1 or team 2 won the game (0 stands for a draw).
score table -
-----------------
t1 t2 result
-----------------
us aus 1
aus sa 2
sa us 0
us nz 1
Desired output -
---------------------------------
team played won lost draw
---------------------------------
aus 2 0 2 0
us 3 2 0 1
nz 1 0 1 0
sa 2 1 0 1
Here's my solution that I came up with, but Is it possible to solve it without using a UNION operator?
select
t1 as team,
count(1) as played,
sum(case when result=1 then 1 else 0 end) as won,
sum(case when result=2 then 1 else 0 end) as lost,
sum(case when result=0 then 1 else 0 end) as draw
from
(select
t1,
t2,
result
from score
union
select
t2,
t1,
case when result=1 then 2
when result=2 then 1
else 0 end as result
from score
) t
group by t.t1
You could UNPIVOT your data via a CROSS APPLY and then perform the aggregation on the results
Example
Select Team
,played = count(1)
,won = sum(case when Val=1 then 1 else 0 end)
,lost = sum(case when Val=2 then 1 else 0 end)
,draw = sum(case when Val=0 then 1 else 0 end)
From score A
Cross Apply ( values (T1,Result )
,(T2,case when result=1 then 2 when result=2 then 1 else 0 end)
) B(Team,Val)
Group By Team
Results
team played won lost draw
aus 2 0 2 0
nz 1 0 1 0
sa 2 1 0 1
us 3 2 0 1

SQL Calculations based by field type and group by the type

Database includes FamID, TicketType and Amt
I want to get a calculation for total amount for each tickettype for each family and sort by family high to low based on total for all tickettypes.
Database values are:
FamID TicketType Amt
1 1 10
1 1 10
1 2 20
1 3 30
2 2 20
2 1 10
2 1 10
2 1 10
2 3 30
3 3 30
3 3 30
3 3 30
Would like results to be
Family Type 1 Type 2 Type 3 Total
3 0 0 90 90
2 30 20 30 80
1 20 20 30 70
Am I trying to do too much?
You never specified your RDBMS, but the following pivot query should work across most major ones with little modification:
SELECT t.`Type 1`, t.`Type 2`, t.`Type 3`,
(t.`Type 1` + t.`Type 2` + 2*t.`Type 3`) AS Total
FROM
(
SELECT FamID AS Family,
SUM(CASE WHEN TicketType = 1 THEN Amt ELSE 0 END) AS `Type 1`,
SUM(CASE WHEN TicketType = 2 THEN Amt ELSE 0 END) AS `Type 2`,
SUM(CASE WHEN TicketType = 3 THEN Amt ELSE 0 END) AS `Type 3`,
FROM Tickets
GROUP BY FamID
) t
ORDER BY t.Total DESC

Counting values from a column and grouping and sorting by a second value

Let's say I have this table:
NAME YEAR SCORE
_____________________
User1 2010 1
User2 2011 3
User3 2012 2
User4 2013 1
User5 2012 1
User6 2011 3
User7 2010 4
User8 2011 1
I would like to create a query whose output looks like this from this data:
YEAR 1 2 3 4
________________________
2010 1 0 0 1
2011 1 0 2 0
2012 1 1 0 0
2013 1 0 0 0
Where the values in the numbered columns is the count of how many times that score appears in the given year. This seems as if it should be easy but I am having trouble figuring out how to wrap my head around writing this query in a way that is static. Ideas?
select YEAR,
count(CASE WHEN SCORE = 1 THEN 1 END) AS `1`,
count(CASE WHEN SCORE = 2 THEN 1 END) AS `2`,
count(CASE WHEN SCORE = 3 THEN 1 END) AS `3`,
count(CASE WHEN SCORE = 4 THEN 1 END) AS `4`
from TABLE
group by year
For a set of Four values
SELECT YEAR, SUM(CASE WHEN SCORE = 1 THEN 1 ELSE 0 END) AS `1`,
SUM(CASE WHEN SCORE = 2 THEN 1 ELSE 0 END) AS `2`,
SUM(CASE WHEN SCORE = 3 THEN 1 ELSE 0 END) AS `3`,
SUM(CASE WHEN SCORE = 4 THEN 1 ELSE 0 END) AS `4`
FROM TABLE
GROUP BY YEAR

How to display the total number of passed and failed students batch wise

I have a table tbl_marksObtained that contains the following data:
stdID sub marks_Obtained
201bct2007 computer 45
201bct2007 Drawing 0
202bct2007 computer 0
203bct2007 Drawing 65
.
230bct2007 computer 77
301bct2008 physics 0
301bct2008 computer 55
.
.
401bct2009 and so on..
Now I would like to display the results as:
year sub pass fail
2007 computer 20 10
2007 Drawing 15 15
2008 computer 28 2
2009 computer 20 10
I obtained the pass fail of particular year and subject by following code:
SELECT
SUM( CASE WHEN marks_obtained > '0' THEN 1 END) AS pass,
SUM( CASE WHEN marks_obtained = '0' THEN 1 END) AS fail
FROM
tblstudentexammarks
WHERE
sub ='computer' AND stdID LIKE '%bce2007'
but how will I get the above results year wise data
select
RIGHT(stdID,4) as year,
sub,
sum(CASE WHEN marks_Obtained>0 then 1 else 0 end) as pass,
sum(CASE WHEN marks_Obtained=0 then 1 else 0 end) as fail
from tblstudentexammarks
group by RIGHT(stdID,4),sub
order by 1
try this:
select stdID [Year],sub,
sum(case when PF='P' then 1 else 0 end) as Pass,
sum(case when PF='F' then 1 else 0 end) as Fail
from(
select RIGHT(stdID,4) stdID,sub,
case when marks_Obtained=0 then 'F' else 'P' end PF
from mark_sheet)a
WHERE
sub ='computer' AND stdID LIKE '%bce2007'
group by stdID,sub