Multliple Pivot tables - sql-server

We have a table like below
.
.
.
.
.
ID WOID InfoCode PersonID PersonSource FieldID FieldName FieldValue
--------------------------------------------------------------------------------------
1 2 AGMDDFR 7 CSS2C 1 Email sg
2 2 AGMDDFR 7 CSS2C 2 Phone 245345
3 2 AGMDDFR 7 CSS2C 3 FAX 345345
4 2 AGMDDFR 7 CSS2C 4 ArticleNumber 345
5 2 AGMDDFR 7 CSS2C 6 Description etete
6 2 ABC 7 CSS2C 12 Enter Email
7 2 AGMDDFR 8 CSS2C 1 Email tet#gmi.com
8 2 AGMDDFR 8 CSS2C 2 Phone 9988776655
9 2 AGMDDFR 8 CSS2C 3 FAX 898383838
10 2 AGMDDFR 8 CSS2C 4 Article Number 777777
11 2 AGMDDFR 8 CSS2C 6 Description asdff
we want output like below based on 'Info Code' we need to extract tables like below.
---1stTable(AGMDDFR)----
WOID PersonID PersonSource Email Phone Fax ArticleNumber Description
-----------------------------------------------------------------------------------------
2 7 CSS2C sg 245345 345345 345 etete
2 8 CSS2C tet#gmi.com 9988776655 898383838 777777 asdff
--2ndTable(ABC)
WOID PersonID PersonSource Enter Email
2 7 CSS2C ssss
Please help me how to solve this issue..

Since you need to return different columns for each InfoCode value, you'll need to look at using dynamic SQL to get the result. This will create a SQL string that contains the list of columns for each parameter. You'll then execute the SQL string to get the final result.
The basic syntax will be:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#InfoCode varchar(10)
DECLARE #ParmDefinition NVARCHAR(500)
set #InfoCode = 'AGMDDFR'
SET #ParmDefinition = '#InfoCode varchar(10)'
select #cols = STUFF((SELECT ',' + QUOTENAME(FieldName)
from yourtable
where InfoCode = #InfoCode
group by FieldName, FieldID
order by FieldId
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT WOID, PersonID, PersonSource, ' + #cols + '
from
(
select WOID, PersonID, PersonSource,
FieldName, FieldValue
from yourtable
where InfoCode = #InfoCode
) x
pivot
(
max(FieldValue)
for FieldName in (' + #cols + ')
) p '
EXEC sp_executesql #query, #ParmDefinition, #InfoCode = #InfoCode;
See SQL Fiddle with Demo

Related

How can I unpivot and then pivot my table so the columns become rows and one column becomes a row?

How can I accomplish this with unpivot and pivot.
I've seen this question asked before and has a solution with case statement and union all
In SQL, how can I count the number of values in a column and then pivot it so the column becomes the row?
and here PIVOT/UNPIVOT multiple rows and columns but I have 20 rows and 24 columns and the query would become very long and I suspect inefficient. Does anyone know how I can do this with unpivot and pivot or is case and union all the only viable option?
Hour A B C D E ... Z
-----------------------------------------
0 4 2 3 0 6 2
1 3 5 7 1 8 7
2 2 6 1 1 4 3
3 2 2 0 3 0 2
4 3 9 6 2 2 8
...
23 6 5 2 3 8 6
Field 0 1 2 3 ...23
-------- -- -- -
A 2 0 2 2 4
B 7 2 8 1 6
....
Z 6 7 7 3 8
This is what I've tried in terms of pivot but I didn't get far:
select B,[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23] from CTE2
pivot(
sum(A)
for hour in ([0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23])) as pvt;
Just to clarify, the numbers in the table are just random numbers I've put to simulate data, they aren't transposed as they should be.
Well, I know you say you've solved it so this probably isn't necessary and you can feel free to use whatever answer you currently have, but here's an example of how you could approach this problem in general.
IF OBJECT_ID('tmpTable', 'U') IS NOT NULL DROP TABLE tmpTable;
CREATE TABLE tmpTable (i INT, a INT, b INT, c INT, d INT);
INSERT tmpTable VALUES (1,69,69,10,1)
, (2,5,0,2,3)
, (3,5,5,5,5)
, (4,1,2,3,4);
DECLARE #applycols NVARCHAR(MAX);
SELECT #applycols = STUFF(
(SELECT ',(' + QUOTENAME(COLUMN_NAME) + ', ''' + COLUMN_NAME + ''')'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmpTable'
AND COLUMN_NAME <> 'i'
FOR XML PATH ('')),1,1,'');
DECLARE #aggcols NVARCHAR(MAX) = '';
SELECT #aggcols += ', MAX(CASE WHEN i = ' + CAST(i AS NVARCHAR(255)) + ' THEN piv.colval END) ' + QUOTENAME(CAST(i AS NVARCHAR(255)))
FROM tmpTable;
DECLARE #SQL NVARCHAR(MAX) = 'SELECT piv.col' + #aggcols + '
FROM tmpTable
CROSS APPLY (VALUES ' + #applycols + ') piv(colval, col)
GROUP BY piv.col;';
EXEC(#SQL);
DROP TABLE tmpTable;
Essentially, it's using dynamic SQL to determine all the columns/values and then using a simple CROSS APPLY / MAX(CASE... to get all the values.

SQL Server Pivot Multiple Values

Using SQL Server 2012.
I have the following table. The Style and colour are passed as a parameter:
Style Colour Size Whse Stock Sales 4WeekSales ATP
ABC123 AS12 10 London 2 3 6 7
ABC123 AS12 12 London 4 6 8 10
ABC123 AS12 14 New York 6 8 9 12
ABC123 AS12 10 New York 7 5 7 5
But need the data to look like this with the sizes along the top:
Whse 10 12 14
Lon
Stock 2 4 6
Sales 3 6 8
4WeekSales 6 8 9
ATP 7 10 12
New York
Stock 7 6
Sales 5 8
4WeekSales 7 9
ATP 5 12
Points to note - the size field needs to be dynamic - sometimes it can be 6 /8/10/12, sometimes it can be XS/S/M/L etc
Also their are more than two whse's - this is just an example.
I did make a start in T-SQL:
use SafetyStock
go
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(Size)
FROM (SELECT p.Size FROM dbo.vw_optimums AS p
GROUP BY p.Size) AS x;
SET #sql = N'
SELECT SKU, Style,' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT SKU, Style, p.Size, p.SAFETYSTOCK
FROM dbo.vw_optimums AS p
) AS j
PIVOT
(
SUM(SAFETYSTOCK) FOR Size IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
PRINT #sql;
EXEC sp_executesql #sql;
However, this works but only pivots on the stock - how do I also pivot by Sales\4WeekSales\ATP and also groupb by the whse?
Thank you in advance.
This is my latest code. If I take the SEQNO out it works, but I need this so the sizes appear along the top correctly e.g. S / M / L / XL / XXL etc or 6/ 8 / 10 / 12
DECLARE #SizeColums VARCHAR(MAX)
DECLARE #Seq Integer
SELECT
#SizeColums = COALESCE(#SizeColums + ',','') + QUOTENAME([Size]),
#Seq = SEQNO
FROM vw_optimums1
GROUP BY [Size],[SEQNO]
ORDER BY [SEQNO]
DECLARE #Sql NVARCHAR(MAX) = N'
SELECT Whse,
[Types],' +
#SizeColums + '
FROM (SELECT * FROM vw_optimums1) t
UNPIVOT (
[Type]
FOR [Types] IN ([Stock],[LWSALES],[L4WSALES],[ATP]) ) up
PIVOT (
MAX([Type])
FOR [Size] IN (' + #SizeColums + ')
) p
'
EXEC sp_executesql #sql;
About the closest I can get you is this.
DECLARE #SizeColums VARCHAR(MAX)
SELECT #SizeColums = COALESCE(#SizeColums + ',','') + QUOTENAME([Size])
FROM vw_optimums
GROUP BY [Size]
DECLARE #Sql NVARCHAR(MAX) = N'
SELECT Whse,
[Types],' +
#SizeColums + '
FROM (SELECT * FROM vw_optimums
) t
UNPIVOT (
[Type]
FOR [Types] IN ([Stock],[Sales],[4WeekSales],[ATP]) ) up
PIVOT (
MAX([Type])
FOR [Size] IN (' + #SizeColums + ')
) p
'
This actually uses UNPIVOT first to get the breakdown by size, then pivots based on size.
You'll get a result like this based on the sample data.
Whse Types 10 12 14
-------- -------------- ----------- ----------- -----------
London 4WeekSales 6 8
London ATP 7 10
London Sales 3 6
London Stock 2 4
New York 4WeekSales 7 9
New York ATP 5 12
New York Sales 5 8
New York Stock 7 6

unable to group by on multiple column in Pivot sql Query

I am working in a restaurant project. I have 4 table for sale module.
order master.
order details.
itemEntry
waiter_info
They require a report which will show each item sale quantity for each waiter.
MENU_NAME MENU_ID PRICE Total Foisal Kamal Sajib
Naan 2 10.00 8 6 2 0
Parata 1 10.00 10 6 4 0
Vaji 3 30.00 15 8 6 1
My query is below:
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(Name)
FROM (SELECT DISTINCT Name FROM Waiter_Info) AS Waiter
print #ColumnName
SET #DynamicPivotQuery = N'
SELECT * from vw_ItemWiseSale
pivot
(
sum(QUANTITY) for WAITER in ('+ #ColumnName +')) as pvt'
EXEC sp_executesql #DynamicPivotQuery
My output is:
MENU_NAME MENU_ID PRICE Total Foisal Kamal Sajib
Naan 2 10.00 20 NULL 2 NULL
Naan 2 10.00 60 6 NULL NULL
Parata 1 10.00 40 NULL 4 NULL
Parata 1 10.00 60 6 NULL NULL
Vaji 3 30.00 30 NULL NULL 1
Vaji 3 30.00 180 NULL 6 NULL
Vaji 3 30.00 240 8 NULL NULL
Please help me to get expected output item wise which mentioned in 3 line.(i,e each row for every item)

Select multi value from another table and put in one string split by -

I have 2 tables in MS SQL Server.
Table 1
ID Name
-------------
10 Series
11 Movie
12 Music
13 Other
Table 2
ID IDCatg Value
---------------------------
1 10 Hannibal
2 10 Blacklist
3 10 POI
4 11 Hitman
5 11 SAW
6 11 Spider man
7 12 taylor swift
8 12 britney spears
I want to select by IDCatg in Table 2 and create a new column in Table 1 like this:
IDCatg Name Value
--------------------------------------------
10 Series Hannibal-Blacklist-POI
11 Movie Hitman-SAW-Spider man
12 Music taylor swift-britney spears
How can I do this by view?
You can do it using STUFF:
SELECT T21.IDCatg, T1.Name,
[Value] = STUFF((
SELECT '-' + T22.[Value]
FROM Table2 T22
WHERE T21.IDCatg = T22.IDCatg
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM Table2 T21 JOIN
Table1 T1 ON T1.ID=T21.IDCatg
GROUP BY T21.IDCatg,T1.Name
Result:
IDCatg Name Value
---------------------------------------------
10 Series Hannibal-Blacklist-POI
11 Movie Hitman-SAW-Spider man
12 Music taylor swift-britney spears
Sample result in SQL Fiddle
EDIT:
When the type of Value is int, you can cast it to varchar:
[Value] = STUFF((
SELECT '-' + CAST(T22.[Value] AS Varchar(MAX))

How to keep column order same in dynamic pivot

I have below mentioned table :
drn RecNum Name Value
----------------------------------------------
1 1 ad1_pk 1
2 1 ad1_address1 P.O. Box 5036
3 1 ad1_address2 NULL
4 1 ad1_address3 NULL
5 1 ad1_ctyfk 56
6 1 ad1_postalcode 80155-5036
7 1 ad1_active Y
8 1 ad1_irstat A
9 1 ad1_irdata NULL
10 1 ad1_at1fk 1
1 2 ad1_pk 2
2 2 ad1_address1 1871 S. Broadway
3 2 ad1_address2 NULL
4 2 ad1_address3 NULL
5 2 ad1_ctyfk 1
6 2 ad1_postalcode 80210
7 2 ad1_active Y
8 2 ad1_irstat A
9 2 ad1_irdata NULL
10 2 ad1_at1fk 1
I am creating the pivot using the below mentioned query:
declare #var nvarchar(max)
declare #sql nvarchar(max)
set #var = stuff((select distinct ',' + name from temp
for xml path('')),1,1,'') -- **this is giving distinct column list but the order of columns get changed..**
set #sql = 'select * from temp
pivot(max(value) for name in (' + #var + ')) as pvt'
exec sp_executesql #sql
Is there a way to keep the order of the columns unchanged? I want the order of columns listed in #var to be same as in the table.
Add a GROUP BY and an ORDER BY clause (to replace the DISTINCT) where you build your column list as follows:
set #var = stuff((select ',' + min(name) from temp GROUP BY drn ORDER BY drn
for xml path('')),1,1,'')
And don't forget the the necessary aggregation (I've used MIN()). Thanks #Ionic.
This is because you're using a DISTINCT in your SELECT query. If you look at the execution plan, you can see DISTINCT SORT operation. This sorts your result based on the DISTINCT columns you specify, in this case it's Name:
To retain the order, you can try this:
set #var = stuff((
select ',' + name
from(
select
name,
drn,
rn = row_number() over(partition by name order by drn)
from temp
)t
where rn = 1
order by drn
for xml path('')),
1,1,'')

Resources