How to write where clause in pivot statement in SQL Server - sql

I need to get records based on project and year
SELECT
*
FROM
(SELECT
Source,
val,
month
FROM
tbl_OrganicResult
CROSS APPLY
(VALUES ('visitors', visitors),
('UniqueVisitors', UniqueVisitors),
('ReturnVisitors', ReturnVisitors)) cs (Source, val)) A
PIVOT (Max(val)
FOR month IN ([jun], [jul)) pv
I need the records with where condition like
select *
from tbl_OrganicResult
where project = 'Homeocare'
Sample data
ProjectName Month Year visitors UniqueVisitors ReturnVisitors
Homeocare Jun 2015 400 33 22
Homeocare Jul 2015 100 10 8
debug test. Aug 2015 15222 122 120
debug test. Jun. 2015 1500 150 15
debug test. Jul 2015 1400 140 14
I'm getting records like this which is not correct, I mean I'm not getting project wise.
How to add where condition to get like where project - 'homeocare' ?
Getting output like this
Source jun jul
ReturnVisitors 8 120
UniqueVisitors 10 122
Visitors 100 15222
I need records like this
Source jun jul
ReturnVisitors. 22 8
UniqueVisitors. 33 10
Visitors 400 100
Sorry for my mistake of giving wrong data (earlier). Here always getting last 2 records and not used where condition to get records project and year wise.

The where clause should go after the cross apply like this:
SELECT
*
FROM
(
SELECT
Source,
val,
Year,
month
FROM
tbl_OrganicResult
CROSS APPLY
(VALUES ('visitors', visitors),
('UniqueVisitors', UniqueVisitors),
('ReturnVisitors', ReturnVisitors)) cs (Source, val)
WHERE ProjectName = 'Homeocare'
) A
PIVOT ( Max(val) FOR Month IN ([jun], [jul]) ) pv
Unless you only have data for one year in your table this query will get you the max value for a month from any year where you have data recorded for that month, for example if you had 100 visitors in June 15 and 200 visitors in June 14 then the value for June 14 would be selected. This might not be what you want.
I would consider doing something like this instead:
SELECT
Source, [Jun-2015], [Jul-2015]
FROM
(
SELECT
Source,
Val,
MonthYear = CONCAT(Month,'-',Year)
FROM
tbl_OrganicResult
CROSS APPLY
(VALUES ('Visitors', visitors),
('UniqueVisitors', UniqueVisitors),
('ReturnVisitors', ReturnVisitors)) cs (Source, Val)
WHERE ProjectName = 'Homeocare'
) A
PIVOT ( MAX(Val) FOR MonthYear IN ([Jun-2015], [Jul-2015]) ) pv ;

in your case you have three months but you are looking for july in place of june and August in place of july just add alias names for those columns
declare #table table (ProjectName varchar(20), Month varchar(20), Year varchar(20), visitors INT, UniqueVisitors INT, ReturnVisitors INT)
insert into #table (ProjectName,Month,Year,visitors,UniqueVisitors,ReturnVisitors)values
('Homeocare' , 'Jun' , 2015 , 400 , 33 , 22),
('Homeocare' , 'Jul' , 2015 , 100 , 10 , 8),
('debug test', 'Aug' , 2015 , 15222 , 122 , 120 )
SELECT source,JUN as Jul,jul as aug FROM (SELECT Source,
val,
month
FROM #table
CROSS apply (VALUES ('visitors',visitors),
('UniqueVisitors',UniqueVisitors),
('ReturnVisitors',ReturnVisitors)) cs (Source, val)) A
PIVOT (max(val)
FOR month IN ([jun],[Jul],
[Aug])) pv

Related

Sum of last 12 months

I have a table with 3 columns (Year, Month, Value) like this in Sql Server :
Year
Month
Value
ValueOfLastTwelveMonths
2021
1
30
30
2021
2
24
54 (30 + 24)
2021
5
26
80 (54+26)
2021
11
12
92 (80+12)
2022
1
25
87 (SUM of values from 1 2022 TO 2 2021)
2022
2
40
103 (SUM of values from 2 2022 TO 3 2021)
2022
4
20
123 (SUM of values from 4 2022 TO 5 2021)
I need a SQL request to calculate ValueOfLastTwelveMonths.
SELECT Year,
       Month,
Value,
SUM (Value) OVER (PARTITION BY Year, Month)
FROM MyTable
This is much easier if you have a row for each month and year, and then (if needed) you can filter the NULL rows out. The reason it's easier is because then you know how many rows you need to look back at: 11.
If you make a dataset of the years and months, you can then LEFT JOIN to your data, aggregate, and then finally filter the data out:
SELECT *
INTO dbo.YourTable
FROM (VALUES(2021,1,30),
(2021,2,24),
(2021,5,26),
(2021,11,12),
(2022,1,25),
(2022,2,40),
(2022,4,20))V(Year,Month,Value);
GO
WITH YearMonth AS(
SELECT YT.Year,
V.Month
FROM (SELECT DISTINCT Year
FROM dbo.YourTable) YT
CROSS APPLY (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12))V(Month)),
RunningTotal AS(
SELECT YM.Year,
YM.Month,
YT.Value,
SUM(YT.Value) OVER (ORDER BY YM.Year, YM.Month
ROWS BETWEEN 11 PRECEDING AND CURRENT ROW) AS Last12Months
FROM YearMonth YM
LEFT JOIN dbo.YourTable YT ON YM.Year = YT.Year
AND YM.Month = YT.Month)
SELECT Year,
Month,
Value,
Last12Months
FROM RunningTotal
WHERE Value IS NOT NULL;
GO
DROP TABLE dbo.YourTable;

Reshaping a table SQL

I am using SQL and currently have a large table that contains data for 1000's of accounts sorted by date:
ID July 2018 August 2018 September 2018 …
1 10 20 30
2 50 40 10
3 20 10 80
I need to reshape the table so the table is displayed like this:
ID Month Value
1 July 2018 10
1 August 2018 20
1 September 2018 30
: : :
I don't know how to do this or if this is even possible. I have tried to use the pivot function in SQL but I have not been successful. Is there a way to do this?
You can use APPLY :
SELECT t.id, tt.*
FROM table t CROSS APPLY
( VALUES ('July 2018', [July 2018]),
('August 2018', [August 2018]),
('September 2018', [September 2018])
) tt (Month, Val);
You can use unpivot - it will work in MSSQL
select t.id, up.months, up.value
from tablename t
unpivot
(
value
for months in ([July 2018], [August 2018], [September 2018])
) up;
You can try with the help of UNION operator:
select id, 'July 2018' as Month, July2018 as value from <table>
UNION
select id, 'August 2018' as Month, August2018 as value from <table>
UNION
select id, 'September 2018' as Month, September2018 as value from <table>

Summing together values from the same table in different databases

I have a table on each database for a region of a company with the number of sales per month like so:
Region1.dbo.SalesPerMonth Region2.dbo.SalesPerMonth
ID Month Sales ID Month Sales
1 Jan 23 1 Jan 21
2 Feb 19 2 Feb 15
3 Jan 31 3 Jan 25
... ... ... ... ... ...
I am looking to write a query to join these tables into one table that shows the sales for the entire company per month, so it has the total sales from all regions added together:
AllRegions
ID Month Sales
1 Jan 44
2 Feb 34
3 Jan 56
... ... ...
I am however new to SQL and am not sure how to go about doing so. Any help or advice on how to write the query would be greatly appreciated.
Union together the two tables, and then aggregate by ID and Month to generate the sum of sales.
SELECT
ID, Month, SUM(Sales) AS Sales
FROM
(
SELECT ID, Month, Sales
FROM Region1.dbo.SalesPerMonth
UNION ALL
SELECT ID, Month, Sales
FROM Region2.dbo.SalesPerMonth
) t
GROUP BY
ID, Month
ORDER BY
ID;
Demo here:
Rextester
Try this:
WITH DataSource AS
(
SELECT *
FROM Region1.dbo.SalesPerMonth
UNION ALL
SELECT *
FROM Region2.dbo.SalesPerMonth
)
SELECT [id]
,[Month]
,SUM(Sales) AS Sales
FROM DataSource
GROUP BY [id]
,[Month]

SQL Pivot Questions [duplicate]

This question already has answers here:
Unpivot with column name
(3 answers)
SQL Unpivot multiple columns Data
(3 answers)
Closed 5 years ago.
I have data like below:
Year January Feb March April
2017 20 15 7 25
Is it possible to format the data to
Year Month Value
- 2017 January 20
- 2017 Feb 15
- 2017 March 7
- 2017 April 25
Thanks a lot for your help. I have been trying to achive this for hours but I am not able to.
This is unpivot, but I prefer using apply:
select v.*
from t outer apply
(values (t.year, 'January', t.January),
(t.year, 'Feb', t.Feb),
(t.year, 'March', t.March),
(t.year, 'April', t.April)
) v(year, month, value);
apply implements something called a "lateral join". This is a lot like a correlated subquery that can return multiple columns. Lateral joins are very powerful -- unpivoting is just the beginning of what they do. But unpivoting is one way to start learning about them.
You can use UNPIVOT for this.
DECLARE #T TABLE (Year INT, January INT, Feb INT, March INT, April INT)
INSERT INTO #T VALUES(2017,20,15,7,25)
SELECT [Year], [Month], [Value] FROM #T
UNPIVOT( [Value] FOR [Month] IN( [January], [Feb], [March], [April] ) ) AS UNPVT
Result
Year Month Value
----------- ----------- -----------
2017 January 20
2017 Feb 15
2017 March 7
2017 April 25

Transpose data in SQL

Can someone assist me on this?
As you can see from the first picture (Original data) I have date in format "Mar-12" and data for 2014,2015,2016 and 2017 year.
Now, I need to insert new column "year" where I need to put the year from Jan-14, Jan-15, Jan-16, Feb-16 etc.
Basically, I need some kind of data transpose, I think.
In the second picture "Final Order" I show in which order I need the data.
I don't know what is dbms.
So, this is how my data (original) looks like:
Customer|Section|Data|Jan-14|Feb-14|Jan-15|Feb-15
Total Fore SR 10 20 30 35
Total Fore TK 5 4 12 10
===================================================
And I need to put the data in this form:
Customer|Section|Data| Year |Jan|Feb|
Total Fore SR 2014 10 20
Total Fore TK 2014 5 4
Total Fore SR 2015 30 35
Total Fore TK 2015 12 10
Given your sample of
create table t (Customer varchar(5),Section varchar(4), Data varchar(2), [Jan-14] int , [Feb-14] int, [Jan-15] int, [Feb-15] int)
insert into #t values
('Total' , 'Fore' , 'SR' , 10 , 20, 30, 35),
('Total' , 'Fore' , 'TK' , 5 , 4, 12, 10)
you can solve this if your sql dialect is ms sql server by unpivoting and then grouping by like so
select customer,section,data,yyyy,
sum(case when mm='Jan' then dts else 0 end) as 'Jan',
sum(case when mm='Feb' then dts else 0 end) as 'Feb'
from
(
select customer,section,data,
dummy,
substring(dummy,1,3) as mm,
concat('20',substring(dummy,5,2)) as yyyy,
dts
from
(
select customer,section,data,
[Jan-14] , [Feb-14] , [Jan-15] , [Feb-15]
from t
) pvt
UNPIVOT
(dts FOR dummy IN
([Jan-14] , [Feb-14] , [Jan-15] , [Feb-15])
)AS unpvt
) x
group by customer,section,yyyy,data
result
customer section data yyyy Jan Feb
-------- ------- ---- ---- ----------- -----------
Total Fore SR 2014 10 20
Total Fore TK 2014 5 4
Total Fore SR 2015 30 35
Total Fore TK 2015 12 10
If your sql dialect does not have unpivot you can
select customer,section,data,yyyy,
sum(case when mm='Jan' then dts else 0 end) as 'Jan',
sum(case when mm='Feb' then dts else 0 end) as 'Feb'
from
(
select customer,section,data,2014 as yyyy,'Jan' as mm,[Jan-14] as dts from t
union all
select customer,section,data,2014 as yyyy,'Feb' as mm,[Feb-14] as dts from t
union all
select customer,section,data,2015 as yyyy,'Jan' as mm,[Jan-15] as dts from t
union all
select customer,section,data,2015 as yyyy,'Feb' as mm,[Feb-15] as dts from t
) x
group by customer,section,yyyy,data
Clearly either method is a pain if you have an unknown/variable number/lots of columns in which case you would need write a script to generate a sql statement for submission to dynamic sql.