SQL query Joining table itself - sql

I have a following table:
TICKER DATE SHAREPRICE
--------------------------------
ABC 1.1.2015 50
XYZ 1.1.2015 100
etc.
I want to make a query, where the result is following:
DATE PRICE(TICKER ABC) PRICE(TICKER XYZ)
--------------------------------------------
1.1.2015 50 100

Use PIVOT in SQL SERVER.
DECLARE #test AS TABLE(TICKER VARCHAR(10), DATE DATETIME, SharePrice INT)
INSERT INTO #test
SELECT 'ABC', '1/1/2015', 50 UNION
SELECT 'XYZ', '1/1/2015', 100
SELECT Date, ABC AS [PRICE(TICKER ABC)], XYZ AS [PRICE(TICKER XYZ)] FROM #test
PIVOT(MAX(SharePrice) FOR Ticker IN(ABC, XYZ)) AS A

In TSQL you can write a query using dynamic pivot as:
DECLARE #cols AS NVARCHAR(MAX),#colsFinal AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ', ' + TICKER
from test1
group by TICKER, [DATE]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsFinal = STUFF((SELECT distinct ', isnull( ' + TICKER +
' ,0) as [PRICE (TICKER ' + TICKER +' )]'
from test1
group by TICKER, [DATE]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT [Date],' + #colsFinal + N' from
(
select [Date], TICKER , SharePrice
from test1
) x
pivot
(
max(SharePrice)
for TICKER in (' + #cols + N')
) p '
exec sp_executesql #query;
DEMO

Related

SQL pivot with multiple column data in one with comma separation

SQL Query Table:
Date Production LineName Buyer Style
2021-04-30 100 A Lev 1a
2021-04-30 200 B Kont 2d
2021-04-30 300 C ABB 4l
2021-04-30 400 A Lev 1a
2021-04-29 600 A BDA 3z
Output need like:
LineName 2021-04-29 2021-04-30
A 600,BDA,3Z 500,Lev,1a
B NULL 200,Kont,2d
C NULL 300,ABB,4l
I started coding and stuck at
DECLARE #query VARCHAR(4000)
,#Dates VARCHAR(4000)
SET #Dates = STUFF((
SELECT DISTINCT '],[' + Cast([Date] As Varchar)
FROM Table_17M
ORDER BY '],[' + Cast([Date] As Varchar)
FOR XML PATH('')
), 1, 2, '') + ']'
SET #query = ';With PivotData
As
(
Select
LineName, -- grouping element
[Date], -- spreading element
PlanProduction-- aggregating element
From Table_17M
)
Select *
From PivotData
Pivot (Sum(PlanProduction) For [Date] In (' + #Dates + ')) As P;'
EXEC (#query);
Any idea please share. It will very much helpful. Thanks.
If you are using SQLServer 2017 or later version then use string_agg() instead of suff(). It's easier to implement and much faster.
select #cols= string_agg(quotename([date]),',') from (select distinct [date] from Table_17M)t
DB-Fiddle
create table Table_17M(Date Date,Production int, LineName varchar(50), Buyer varchar(50), Style varchar(50));
insert into Table_17M values('2021-04-30', 100, 'A', 'Lev', '1a');
insert into Table_17M values('2021-04-30', 200, 'B', 'Kont', '2d');
insert into Table_17M values('2021-04-30', 300, 'C', 'ABB' , '4l');
insert into Table_17M values('2021-04-30', 400, 'A', 'Lev' , '1a');
insert into Table_17M values('2021-04-29', 600, 'A', 'BDA' , '3z');
Query:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',' + quotename([date])
FROM Table_17M
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'select LineName , ' + #cols + ' from
(
select LineName,[date],concat(sum(production),'','',max(buyer),'','',string_agg(Style,'','')) other_columns
from Table_17M
group by LineName,[date]
) x
pivot
(
max(other_columns)
for [date] in (' + #cols + ')
) p
group by LineName , ' + #cols
execute( #query)
Output:
LineName
2021-04-29
2021-04-30
A
600,BDA,3z
500,Lev,1a,1a
B
null
200,Kont,2d
C
null
300,ABB,4l
db<fiddle here

Convert Columns values into Rows in SQL 2008

It would be great if you can help me to convert Column into Rows in SQL Table.
Let say, I have 3 columns called:
Employee_ID
Shift_Date
Shift_ID
Currently it come up like this:
Table Like this
I want to appear like that as the result -
Result Table
But I want value in it, can you guys please help. Thanks.
This is a query I wrote but still error:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(shift_date)
from dbo.tbl_Multi_Shift_Employee WHERE Shift_Date BETWEEN CONVERT(DATE, '01/02/2018 00:00:00',103) AND CONVERT(DATE, '28/02/2018 00:00:00',103)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Employee_ID, total, Department_ID, shift_id, ' + #cols + ' from
(
select count(*) over(partition by t.Employee_ID) total,
s.Department_ID,
t.Employee_ID,
t.shift_id
from dbo.tbl_Multi_Shift_Employee t
inner join dbo.tbl_department s
on t.Department_ID = s.Department_ID
) x
pivot
(
count(shift_id)
for shift_id in (' + #cols + ')
) p '
PRINT #query
execute(#query)
First you must to remove shift_id from primary select because is used as pivot.
Second, change shift_id with shift_date that is the correct column you are using as pivot columns.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(shift_date)
from dbo.tbl_Multi_Shift_Employee WHERE Shift_Date BETWEEN CONVERT(DATE, '01/02/2018 00:00:00',103) AND CONVERT(DATE, '28/02/2018 00:00:00',103)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Employee_ID, total, Department_ID, ' + #cols + ' from
(
select count(*) over(partition by t.Employee_ID) total,
s.Department_ID,
t.Employee_ID,
t.shift_id,
t.shift_date
from dbo.tbl_Multi_Shift_Employee t
inner join dbo.tbl_department s
on t.Department_ID = s.Department_ID
) x
pivot
(
count(shift_id)
for shift_date in (' + #cols + ')
) p '
PRINT #query
execute(#query)

How to create a SQL Server Pivot query?

I want to create sql query result. I want to dynamically create because of inventory locations are one or more. (Example.. CTE)
Item_id Location Qty
--------------------------
1 a 1
2 b 2
3 c 3
3 a 1
2 c 2
1 b 3
Result is....
Item_id a_Location_Qty b_Location_Qty c_Location_Qty
-------------------------------------------------------
1 1 3 0
2 0 2 2
3 1 0 3
Please try below code
Create Table #Stack10072017040904(Item_id varchar(100),Location varchar(100),Qty int)
insert into #Stack10072017040904 select '1','a','1'
insert into #Stack10072017040904 select '2','b','2'
insert into #Stack10072017040904 select '3','c','3'
insert into #Stack10072017040904 select '3','a','1'
insert into #Stack10072017040904 select '2','c','2'
insert into #Stack10072017040904 select '1','b','3'
select Item_id,Isnull(a,0) a_Location_Qty
,isnull(b,0)b_Location_Qty
,isnull(c,0)c_Location_Qty
from #Stack10072017040904
pivot
(Sum(Qty) for Location in ([a],[b],c) )pvt
drop table #Stack10072017040904
Try this Dynamic Sql
Declare
#Sql nvarchar(max),
#dynamicCol nvarchar(max),
#dynamicCol2 nvarchar(max)
--Create columns Dynamically
SELECT #dynamicCol=STUFF((SELECT DISTINCT ', '+ QUOTENAME(Location )
From #Stack10072017040904 For XML PATH ('')),1,1,'')
SELECT #dynamicCol2=STUFF((SELECT DISTINCT ', '+ 'ISNULL ('+ QUOTENAME(Location )+ ','+'''0'''+')' +' AS '+Location+'_Location_Qty'
From #Stack10072017040904 For XML PATH ('')),1,1,'')
SET #Sql='
SELECT [Item_id] ,'+ #dynamicCol2 +' From
(
SELECT * From
#Stack10072017040904
)AS Src
PIVOT
(
MAX([Qty]) For [Location] IN ('+#dynamicCol+')
)
AS Pvt'
PRINT #Sql
EXEC(#Sql)
Result
Item_id a_Location_Qty b_Location_Qty c_Location_Qty
-------------------------------------------------------
1 1 3 0
2 0 2 2
3 1 0 3
Build columns dynamically and use a dynamic PIVOT:
Create Table #Test(Item_id varchar(100),Location varchar(100),Qty int)
insert into #Test values( '1','a','1')
insert into #Test values( '2','b','2')
insert into #Test values( '3','c','3')
insert into #Test values( '3','a','1')
insert into #Test values( '2','c','2')
insert into #Test values( '1','b','3')
DECLARE #cols1 AS NVARCHAR(MAX), #cols2 AS NVARCHAR(MAX), #query AS NVARCHAR(MAX);
SET #cols1 = STUFF((SELECT distinct ', isnull(' + quotename(s.Location) + ', 0) as ' + quotename(s.Location)
FROM #Test s
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #cols2 = STUFF((SELECT distinct ',' + quotename(s.Location)
FROM #Test s
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Item_id, ' + #cols1 + ' from
(
select Item_id
, Location
, Qty
from #Test
) x
pivot
(
max(qty)
for Location in (' + #cols2 + ')
) p '
execute(#query)
drop table #Test

Dynamic Pivot Error in sql server

I used the above code from the link. But I recieve an error as
Msg 8156, Level 16, State 1, Line 14 The column 'Factory' was
specified multiple times for 'p'
Efficiently convert rows to columns in sql server
Here is my table :
TEST
ID score Check TotalofScore
------ ----- ------- ------------
867439 1 factory 1
867439 1 Plant 1
867442 1 factory 1
867442 1 Plant 1
923991 1 Warehouse 1
923991 1 Plant 1
923930 1 factory 1
923930 1 Plant 1
923101 1 Warehouse 1
923101 1 Plant 1
Here's my try
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check],
[ID]
ORDER BY [ID]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = N'SELECT ' + #cols + N' from
(SELECT TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM TEST) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N') ) p '
EXEC Sp_executesql #query;
Expected Result :
ID TotalofScore factory Plant Warehouse
------ ------------ ------- ----- ---------
867439 1 1
867439 1 1
867442 1 1
867442 1 1
923991 1 1
923991 1 1
923930 1 1
923930 1 1
923101 1 1
923101 1 1
As mentioned in Error You cannot specify same column name more than once in Pivot like
..pivot (SUM (T.[score])
for T.[check] in ([factory,[Plant],[factory]..))p
Change your #cols initialization like this
SELECT #cols = Stuff((SELECT DISTINCT ',' + Quotename([check])
FROM TEST
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
Or
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
Update : To convert the Dynamic Pivot into procedure and insert the result into new table
create procedure dbname.schemaname.DynamicPivotProcedure
as
begin
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = N'SELECT ID, [Total Of Score],' + #cols + N' from
(SELECT TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM TEST) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N') ) p '
EXEC Sp_executesql #query;
end
go
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
begin
DROP TABLE #MyTempTable
end
SELECT * INTO #MyTempTable FROM
OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
'EXEC dbname.schemaname.DynamicPivotProcedure')
SELECT * FROM #MyTempTable
Remove the Id from GROUP BY and ORDER By clause. So that you get the DISTINCT Check columns.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME([check])
from #Sample
group by [Check]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ID, [Total Of Score], ' + #cols + N' from
(
SELECT
TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM #Sample AS TEST
) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N')
) p '
exec sp_executesql #query;

Convert vertical sql result into horizontal output with Group by fields in MS SQL Server

I have a table( in SQL Server 2008) which has vertical sales transactions data, i would like to convert vertical output to horizontal output, i tried to use PIVOT, but some how not getting idea how to apply group by on PIVOT, as i want Sum based on AccountHeadID, TransType and IsPast Column.
Sample Table
CREATE TABLE Trans
([TransID] int,
[CustID] int,
[AccountHeadID] int,
[TransType] varchar(100),
[IsPast] bit,
[Amount] int)
;
INSERT INTO Trans
([TransID],CustID, [AccountHeadID], [TransType], [IsPast],[Amount])
VALUES
(1, 1, 1, 'Sales',1,1000),
(2, 1, 1, 'Sales',0,500),
(3, 1, 1, 'Sales',0,400),
(4, 1, 1, 'Return',0,300),
(5, 1, 1, 'Return',0,200),
(6, 1, 1, 'Return',0,100),
(7, 1, 1, 'Return',1,150),
(8, 1, 2, 'Sales',1,2000)
Current Query
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(AccountHeadID)
from Trans
group by AccountHeadID
order by AccountHeadID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT CustID,' + #cols + '
from
(
SELECT
a.CustID,
a.AccountHeadID,
a.TransType,
a.Amount,
a.isPast
FROM Trans a
) x
pivot
(
sum(Amount)
for AccountHeadID in (' + #cols + ')
) p '
execute sp_executesql #query;
Expected Output
CustID | Account-HeadID-TransType-IsPast[1-Sales-Past] | Account-HeadID-TransType-IsCurrent[1-Sales-Current] | Account-HeadID-TransType-IsCurrent[1-Return-Past] | Account-HeadID-TransType-IsCurrent[1-Return-Current] | Account-HeadID-TransType-IsCurrent[2-Sales-Past]| ...
1 |1000 | 900 (500 + 400) |150 | 600[300+200+100] |2000
See SQL Fiddle with Demo
Any suggestion or input are most welcome!
Thanks
Suresh
Try this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(CONVERT(NVARCHAR(10),AccountHeadID) + N'-' + TransType + N'-' + CONVERT(NVARCHAR(10),IsPast))
from Trans
group by AccountHeadID, TransType, IsPast
order by AccountHeadID, TransType, IsPast
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
--select #cols
set #query = 'SELECT CustID,' + #cols + '
from
(
SELECT
a.CustID,
CONVERT(NVARCHAR(10),AccountHeadID) + N''-'' + TransType + N''-'' + CONVERT(NVARCHAR(10),IsPast) Acct,
a.Amount
FROM Trans a
) x
pivot
(
sum(Amount)
for Acct in (' + #cols + ')
) p '
execute sp_executesql #query;
SQL Fiddle