Row as column in SQL Server 2008 - sql

I am working with SQL Server 2008. I have a temp table which returns the this result
Location Month value
US January 10
US February 10
US March 10
US April 10
US May 10
US June 10
UK January 10
UK January 10
UK February 10
UK February 10
UK March 10
UK March 10
UK April 10
UK April 10
UK May 10
UK May 10
UK June 10
UK June 10
I want to get the result as below
Location January February March Q1 April May June Q2
US 10 10 10 30 10 10 10 30
UK 20 20 20 60 20 20 20 60
How to query to get the above result using SQL Server 2008?

You can use this query, you have to complete it to fit your needs with all missing months/quarters:
select Location
,sum(case when [Month] = 'January' then value else 0 end) as January
,sum(case when [Month] = 'February' then value else 0 end) as February
,sum(case when [Month] = 'March' then value else 0 end) as March
,sum(case when [Month] in ( 'January', 'February', 'March')
then value else 0 end) as Q1
...
-- Repeat months...
...
,sum(value) as AllMonthTotal
from myTempTable
group by Location
-- UNION to get rowwise total
union
select 'TOTAL'
,sum(case when [Month] = 'January' then value else 0 end) as January
,sum(case when [Month] = 'February' then value else 0 end) as February
,sum(case when [Month] = 'March' then value else 0 end) as March
,sum(case when [Month] in ( 'January', 'February', 'March')
then value else 0 end) as Q1
...
-- Repeat months...
...
,sum(value) as AllMonthTotal
from myTempTable
There's also the PIVOT method:
Using PIVOT in SQL Server 2008
MSSQL dynamic pivot column values to column header

Related

How to get data from date

Hi I would like to get data from date for users. I ve got a table with all months but i would like to get how much they earn on month
user
month
money
1
january
10
2
january
1
1
april
100
2
april
1000
1
march
0
2
march
1
And result should be:
user
money_on_april
money_on_march
1
100
0
2
1000
1
3
0
0
Assuming you want a column for every month, or a certain subset of months:
SELECT
user,
SUM(CASE month WHEN 'january' THEN money ELSE 0 END) As money_on_january,
SUM(CASE month WHEN 'february' THEN money ELSE 0 END) As money_on_february,
...
FROM
YourTable
GROUP BY
user
If you only want columns for the months which exist in the table, then you'll need to use dynamic SQL instead.
If you are using MS SQL, Try PIVOT
SELECT * FROM [Your Table]
PIVOT(
SUM([money])
FOR [month] IN ([january],[april],[march])
)pvt

Performing subtraction in SQL/finding the balance

SQL table here: http://sqlfiddle.com/#!9/abe1da/9
Current Table:
Year
Month
Type
Accounts
Amount
2021
1
Actual
abc
20
2021
1
Actual
def
30
2021
1
Actual
ghi
40
2021
1
Actual
X
7
2021
1
Actual
Y
3
2021
1
Actual
final
105
Expected
Year
Month
Type
Accounts
Amount
2021
1
Actual
abc
20
2021
1
Actual
def
30
2021
1
Actual
ghi
40
2021
1
Actual
X
7
2021
1
Actual
Y
3
2021
1
Actual
final
105
2021
1
Actual
BALANCE
5
SQL Attempt
select year, month, type,
case when accounts in ('abc') then 'abc'
when accounts in ('def') then 'def'
when accounts in ('ghi') then 'ghi'
when accounts in ('X') then 'x'
when accounts in ('Y') then 'Y'
when accounts in ('final') then 'final'
else 'balance'
end as account_2
,
sum
(
(case when accounts in ('abc','def','ghi','final','x','y') then amount
else
(
(case when accounts in ('final') then (amount))-
(case when accounts in ('abc','def','ghi','x','y') then -amount else 0))
)
from new
Note: That balance of 5 represents thousands of small accounts which currently do not form part of a database.
If I understand correctly:
select Year, Month, Type, Accounts, Amount
from new
union all
select year, month, type, 'balance',
(sum(case when accounts = 'final' then amount else 0 end) -
sum(case when accounts <> 'final' then amount else 0 end)
)
from new
group by year, month, type;
Here is a db<>fiddle.

How do i transform calendar year column to multiple year to months column based on months column and calendar year columns

I have data like this
id MoYear CalenderYear jan feb mar dec
1 2017 2017 1 2 4 0
1 2017 2018 1 0 6 10
2 2018 2018 80 5 8 22
3 2017 2018 30 12 0 3
Now i want ouput like this
id MOyear jan_17 feb_17 mar_17 dec_17 jan_18 feb_18 mar_18 dec_18
1 2017 1 2 4 0 1 0 6 10
2 2018 null null null null 80 5 8 22
3 2017 null null null null 30 12 0 3
I have calendar year column and months columns, based on the calendar year and months column i need to make multiple year-months columns.
I can get to the solution by unpivoting and then after back to pivot. But, the data is so large it takes a lot of memory. The performance is very bad.
Not sure if this will be better approach but you can achieve your output using case statement as well if you don't want to do pivot/unpivot.
Data Creation:
select 1 as ID, 2017 as MOYEar, 2017 as calenderyear, 1 as Jan, 2 as feb,
4 as mar, 0 as dece into #temp union all
select 1 as ID, 2017 as MOYEar, 2018 as calenderyear, 1 as Jan, 0 as feb,
6 as mar, 10 as dece union all
select 2 as ID, 2018 as MOYEar, 2018 as calenderyear, 80 as Jan, 5 as feb,
8 as mar, 22 as dece union all
select 3 as ID, 2017 as MOYEar, 2018 as calenderyear, 30 as Jan, 12 as feb,
0 as mar, 3 as dece
Query:
Select ID, MOYEar, max(case when calenderyear = '2017' then Jan else null end) as Jan_17,
max(case when calenderyear = '2017' then Feb else null end ) as Feb_17,
max(case when calenderyear = '2017' then Mar else null end ) as Mar_17,
max(case when calenderyear = '2017' then Dece else null end) as Dece_17,
max(case when calenderyear = '2018' then Jan else null end ) as Jan_18,
max(case when calenderyear = '2018' then Feb else null end ) as Feb_18,
max(case when calenderyear = '2018' then Mar else null end ) as Mar_18,
max(case when calenderyear = '2018' then Dece else null end) as Dece_18 from #temp
Group by ID, MOYEar
Output:
ID MOYEar Jan_17 Feb_17 Mar_17 Dece_17 Jan_18 Feb_18 Mar_18 Dece_18
1 2017 1 2 4 0 1 0 6 10
3 2017 NULL NULL NULL NULL 30 12 0 3
2 2018 NULL NULL NULL NULL 80 5 8 22

SQL Union in Separate Columns

I made a database to enter all my headache and migraine tracking data into. I'm pulling some queries that show counts of different headache severity by month for a certain year. I have one query that gets all headaches by month, another gets headaches under a certain severity, and the last gets headaches over a certain severity. There are two columns I'm using in the database: HeadacheDate and Severity. I'd like to do a query that would have the following columns as output:
Month, Count of All Headaches, Count of Headaches under 6 Severity,
Count of Headaches Over 5 Severity
I've made a union query that takes 3 queries and gives me the data I want but I just can't figure out how to do a query that will move the data around to give me the column format I want.
Here are my union queries:
SELECT
DateName(month, DateAdd(month, MONTH(HeadacheDate), -1)) AS
HeadacheMonth,
COUNT(Severity) as SeverityCount
FROM
Headaches
WHERE
Severity > 0 AND YEAR(HeadacheDate) = 2013
GROUP BY
MONTH(HeadacheDate)
UNION
SELECT
DateName(month, DateAdd(month, MONTH(HeadacheDate), -1)) AS HeadacheMonth,
COUNT(Severity) as SeverityCount
FROM
Headaches
WHERE
Severity > 0 AND Severity < 6 AND YEAR(HeadacheDate) = 2013
GROUP BY
MONTH(HeadacheDate)
UNION
SELECT
DateName(month, DateAdd(month, MONTH(HeadacheDate), -1)) AS HeadacheMonth,
COUNT(Severity) as SeverityCount
FROM
Headaches
WHERE
Severity > 5 AND YEAR(HeadacheDate) = 2013
GROUP BY
MONTH(HeadacheDate);
This returns results something like this:
April 3
April 11
April 14
August 5
August 10
August 15
December 2
December 11
December 13
July 5
July 6
July 11
June 4
June 10
June 14
March 1
March 2
March 3
May 5
May 8
May 13
November 1
November 13
November 14
October 4
October 9
October 13
September 4
September 10
September 14
What I want is this:
Month, Count of All Headaches, Count of Headaches under 6 Severity, Count of Headaches Over 5 Severity
January, 20, 15, 5
February, 18, 13, 5
and so on.
I'd also like to include months where one of the count fields could be zero.
You can use conditional grouping:
SELECT
[HeadacheMonth] = DATENAME(month, DateAdd(month , MONTH(HeadacheDate), -1))
,[SeverityCountTotal] = COUNT(CASE WHEN Severity > 0 THEN 1 END)
,[SeverityCount_1_5] = COUNT(CASE WHEN Severity > 0
AND Severity < 6 THEN 1 END)
,[SeverityCount_6] = COUNT(CASE WHEN Severity > 5 THEN 1 END)
FROM Headaches
WHERE YEAR(HeadacheDate) = 2013
GROUP BY MONTH(HeadacheDate);
YEAR(HeadacheDate) = 2013 is not SARGable so if index exits on that column query optimizer will skip it.You could consider using:
HeadacheDate >= '2013-01-01T00:00:00' AND HeadacheDate < '2014-01-01T00:00:00'
SELECT Month
,COUNT(Severity) AS ALL
,SUM(CASE WHEN Severity<6 THEN 1 ELSE 0 END) AS SevUn6
,SUM(CASE WHEN Severity>5 THEN 1 ELSE 0 END) AS SevOv5
FROM <table>
GROUP BY Month

How to maintain a running balance in a month wise report

SELECT *
FROM
(SELECT
YEAR (DateOfTransaction) AS year,
LEFT(DATENAME(MONTH, DateOfTransaction), 3) AS month,
SUM(CASE WHEN TransTypeName LIKE 'credit%' THEN amount ELSE 0 END) -
SUM(CASE WHEN TransTypeName LIKE 'Debit%' THEN amount ELSE 0 END) AS Balance
FROM
.............) AS t
PIVOT (SUM(balance) FOR month IN (jan, feb, march, ...., Dec)) AS pvt
This query returns a month-wise report account balance. I want a result is running balance.
Example:
January month I credit 5000, February month I credit 2000
My query result is
year jan feb march...dec
2014 5000 2000 null ..null
I want a result like this:
year jan feb march...dec
2014 5000 7000 null ..null
(5000+2000)
Try this
SELECT year,Jan = Jan, Feb = isnull(Jan,0)+isnull(Feb,0),....
FROM
(SELECT
YEAR (DateOfTransaction) AS year,
LEFT(DATENAME(MONTH, DateOfTransaction), 3) AS month,
SUM(CASE WHEN TransTypeName LIKE 'credit%' THEN amount ELSE 0 END) -
SUM(CASE WHEN TransTypeName LIKE 'Debit%' THEN amount ELSE 0 END) AS Balance
FROM
.............) AS t
PIVOT (SUM(balance) FOR month IN (jan, feb, march, ...., Dec)) AS pvt)t
Or you can simply add a temp table which stores numbers from 1 to 12
inner join #temp on n>=datepart(mm,DateofTransaction) group by year(transaction), n