SQL: PIVOT with join - sql

Newbie question:
I have table below
Period Customer Balance
40 1 10
40 2 15
39 1 9
38 1 10
38 2 20
I would like to order it so that I have one column for each period,
Customer BalancePeriod38 BalancePeriod39 BalancePeriod40
1 10 9 10
2 15 . 20
Is this possible?

You can pivot the data using aggregation with case:
select customer,
sum(case when period = 38 then balance else 0 end) as balance_period_38,
sum(case when period = 39 then balance else 0 end) as balance_period_39,
sum(case when period = 40 then balance else 0 end) as balance_period_40
from your_table
group by customer;

Related

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

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

SQL Aggregate on Two tables

Table A has millions of records from 2014, Using Oracle
ID Sales_Amount Sales_Date
1 10 20/11/2014
1 10 22/11/2014
1 10 22/12/2014
1 10 22/01/2015
1 10 22/02/2015
1 10 22/03/2015
1 10 22/04/2015
1 10 22/05/2015
1 10 22/06/2015
1 10 22/07/2015
1 10 22/08/2015
1 10 22/09/2015
1 10 22/10/2015
1 10 22/11/2015
Table B
ID ID_Date
1 22/11/2014
2 01/12/2014
I want sum of totals for 6 months as well as 1 year for ID 1 taking starting
date from Table B as 22/11/2014
Output Sales_Amount_6Months Sales_Amount_6Months
1 70 130
Shall I use add_months in this case?
Yes, you can use ADD_MONTHS() and conditional aggregation :
SELECT b.id,
SUM(CASE WHEN a.sales_date between b.id_date AND ADD_MONTHS(b.id_date,6) THEN a.sales_amount ELSE 0 END) as sales_6_month,
SUM(CASE WHEN a.sales_date between b.id_date AND ADD_MONTHS(b.id_date,12) THEN a.sales_amount ELSE 0 END) as sales_12_month
FROM TableB b
JOIN TableA a
ON(b.id = a.id)
GROUP BY b.id

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

How to turn repeated ranking(1-5) row data to column data in TSQL

I have a table data:
ID Sale Weekday
1 12 1
2 15 2
3 16 3
4 17 4
5 18 5
6 11 1
7 13 2
8 14 3
9 15 4
10 20 5
11 25 1
12 14 2
13 18 3
14 21 4
15 11 5
.. ..
I'd like to turn it into:
Mo Tu We Th Fr
12 15 16 17 18
11 13 14 15 20
25 14 18 21 11
..
Thank you!
Try this
SELECT SUM(case when Weekday = 1 then Sale else 0 end) as mn,
SUM(case when Weekday = 2 then Sale else 0 end) as Tu,
SUM(case when Weekday = 3 then Sale else 0 end) as We,
SUM(case when Weekday = 4 then Sale else 0 end) as Th,
SUM(case when Weekday = 5 then Sale else 0 end) as Fr
FROM
(
SELECT *,
Row_number()OVER(partition by weekday ORDER BY ID ) as seq_no
FROM tablename
) A
Group by seq_no
As mentioned in sample data if your table has all 5 days for all the week
SELECT SUM(case when Weekday = 1 then Sale else 0 end) as mn,
SUM(case when Weekday = 2 then Sale else 0 end) as Tu,
SUM(case when Weekday = 3 then Sale else 0 end) as We,
SUM(case when Weekday = 4 then Sale else 0 end) as Th,
SUM(case when Weekday = 5 then Sale else 0 end) as Fr
FROM
(
SELECT *,
( ( Row_number()OVER(ORDER BY ID ) - 1 ) / 5 ) + 1 seq_no
FROM tablename
) A
Group by seq_no
SQL FIDDLE DEMO
You could use the pivot operator together with a partitioned row_number like this:
select
max([1]) as 'Mo',
max([2]) as 'Tu',
max([3]) as 'We',
max([4]) as 'Th',
max([5]) as 'Fr'
from
(
select *, row_number() over (partition by weekday order by id) rn
from your_table
) a
pivot (max(sale) for weekday in ([1],[2],[3],[4],[5])) p
group by rn;

Total of Multiple COUNT SELECTS from the multiple tables not working

I have A attendance report in which I want to show report day wise like this :
I can calculate Sum individually , But not the total of all Sum
My StudentAttendance Table :
ID ClassID SubjectID Day10 Day11 Day12 Day13 Day14 Day15 ProfessorID
215 23 46 P 36 36
216 23 47 P 36
217 23 48 P 36 P 36
218 17 35 P 28
I have Tried this Query :
select ClassID,
sum(case when Day14= 'P' then 1 else 0 end) Present,
sum(case when Day14= 'A' then 1 else 0 end) Absent,
sum(case when Day14= 'L' then 1 else 0 end) Leave
from studentattendance
group by ClassID,Day14
I tried Sum(Present.Absent,Leave)..But not working What I am missing ??
There is no SQL syntax for a SELECT with multiple FROM clauses(WITHOUT nesting).
Perhaps you want something like this?
select
classID,
count(Day14) Total,
sum(case when Day14='P' then 1 else 0 end) Present,
sum(case when Day14='A' then 1 else 0 end) Absent,
sum(case when Day14='L' then 1 else 0 end) Leave
from studentattendance
group by classID
Here Total is merely the total number of records in each classID. The sum(case..when..) statements simulates a selective count() only when certain condition is satisfied (Day14 is either Present,Absent or Leave). Note that there is no guarantee that the Total to be equal to Present+Absent+Leave if you expect values other than these 3 to be present in the column Day14