SQL Pivot Questions [duplicate] - sql

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

Related

Querying an SQL table to get all new values in a column according to filter in another column

Sorry I couldn't make the question clearer, let me explain it here.
I have a table that has two columns:
year, ID
------------
2013, 01
2013, 27
2013, 33
2014, 22
2014, 33
2014, 01
2014, 13
2015, 45
2015, 13
2015, 22
What I want to do is the following: check all new IDs that appeared in 2014 from 2013, and all new IDs that appeared in 2015 from 2014, and so on and so forth...
So, from the example above, the expected answer to my query should be a table like:
year, new
-------------
2014, 2
2015, 1
Since in 2014 there are two new IDs in relation to 2013 (22 and 13), and in 2015 there is one new ID in relation to 2014 (45).
Sorry for the horrible formatting, I'm new to this site. Any help is appreciated, thanks.
If I understand correctly, you want lag():
select year, count(*)
from (select t.*, lag(year) over (partition by id order by year) as prev_year
from t
) t
where prev_year is null or prev_year < year - 1
group by year;
You need to find the all codes that didn't exist with a year y - 1 that shower at year y:
with cte as
(
select cast(2013 as int) as year, '01' as id
union select 2013, 27
union select 2013, 33
union select 2014, 22
union select 2014, 33
union select 2014, '01'
union select 2014, 13
union select 2015, 45
union select 2015, 13
union select 2015, 22
)
select year, count(*) from cte a where not exists(select 1 from cte b where a.year -1 = b.year and a.id = b.id)
and a.year -1 in (select distinct year from cte)
group by year

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>

How to write where clause in pivot statement in SQL Server

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

How to add years to date in SQL? [duplicate]

This question already has answers here:
How automatically add 1 year date to an existing date in SQL Server
(3 answers)
Closed 9 years ago.
How to add 2 years to date in SQL.
select left(cast(D as datetime) ,11) from table
In the above query how can i add 2 years.
Output is,
Jan 1 2012
Jan 2 2012
Jan 3 2012
Jan 4 2012
but i want output as,
Jan 1 2014
Jan 2 2014
Jan 3 2014
Jan 4 2014
Thank you
DateAdd() is the function you want http://technet.microsoft.com/en-us/library/ms186819.aspx
SELECT DateAdd(yy, 2, Cast(d As datetime))
select dateadd(yy,2,getdate())
finally i got, Query is SELECT left(DateAdd(yy, 2, Cast(d As datetime)),11) from table
You can use convert instead of the left:
SELECT CONVERT(VARCHAR, DATEADD(year, 2, CAST(d AS DATETIME)), 107) FROM table

Calculate substraction by a specific quarter of year

I have some records after SQL generating:
YEARS MONTHS SUMMONTH SUMQUARTER QTR
----- ------ -------- ---------- ---
2009 Jan 363639 855922 1
2009 Feb 128305 855922 1
2009 Mar 363978 855922 1
2009 Apr 376633 1058871 2
2009 May 299140 1058871 2
2009 Jun 383098 1058871 2
2009 Jul 435000 1063577 3
2009 Aug 266227 1063577 3
2009 Sep 362350 1063577 3
2009 Oct 449366 1017906 4
2009 Nov 280943 1017906 4
2009 Dec 287597 1017906 4
2010 Jan 418277 661083 1
2010 Feb 129895 661083 1
2010 Mar 112911 661083 1
2010 Apr 163593 685625 2
2010 May 228505 685625 2
2010 Jun 293527 685625 2
2010 Jul 451608 1044364 3
2010 Aug 356683 1044364 3
2010 Sep 236073 1044364 3
2010 Oct 247365 798925 4
2010 Nov 414100 798925 4
2010 Dec 137460 798925 4
24 rows selected
The SUMQUARTER column sum up each quarter of a year...
The qtr specify it belongs to which quarter.
The problem is how to have a subtraction of sumquarter between 2 different years to get the specific query result?
The difference is not the: max value-min value.
It is the user-defined value that he want to input...
Let say...
For example, the user want to see the substraction(sumquarter) between 2009 qtr=2 and 2010 qtr=2,
user may change the parameter(years,qtr) of sql to view the record.
This mean the result should be: (1058871 - 685625)
Here is the SQL that I am currently using:
select years,months,summonth,sumquarter,qtr
from(
select years,months,summonth,sumhour,hours,to_char(ym, 'Q') qtr,
sum(sumhour) over(partition by years || to_char(ym, 'Q') order by years || to_char(ym, 'Q')) sumquarter,ym,
count(days) over(partition by years,months,hours) days_month
from(
select years, months, days, hours, mins, sumHour,
SUM (sumHour) OVER (PARTITION BY years,months,days) sumDay,
SUM (sumHour) OVER (PARTITION BY years,months) sumMonth,
SUM (sumHour) OVER (PARTITION BY years) sumyear,
to_date(years || months, 'YYYYMon', 'NLS_DATE_LANGUAGE=American') ym
from (
SELECT x.years, x.months, x.days, x.hours, x.mins, sum(x.value) as sumHour
FROM xmltest,
XMLTABLE ('$d/cdata/name' passing doc as "d"
COLUMNS
years integer path 'year',
months varchar(3) path 'month',
days varchar(2) path 'day',
hours varchar(2) path 'hour',
mins varchar(2) path 'minute',
value float path 'value'
) as X
group by x.years, x.months, x.days, x.hours, x.mins
order by x.years, x.months, x.days
)
)
)
group by years,months,summonth,sumquarter,qtr,ym
order by ym
The sql pattern maybe something like this:...??
select ((select sumquarter from table where years=2009 and qtr=2) - (select sumquarter from table where years=2010 and qtr=2)) from table
Actually, it doesn't work...
The result maybe look in this view:
SUBTRACT
----------
373246
Thanks everyone helps!!:)
I'd use the following:
select
((select sumquarter from table where years=2009 and qtr=2 and rownum=1) -
(select sumquarter from table where years=2010 and qtr=2 and rownum=1)) as substract
from dual
try this query:
select (case when years=2009 and qtr=2 then sumquater end) - (case when years=2010 and qtr=2 then sumquater end) from table