SQL Pivot Query with aggregation & Total - sql

Table-A
ProductId
BrandName
1
Brand-1
2
Brand-2
3
Brand-3
Table-B
DCDate
DCNo
ProductId
Weight
2021-03-09
3
1
12.5
2021-03-09
3
1
12.6
2021-03-09
3
1
12.5
2021-03-09
3
2
10.5
2021-03-09
3
2
10.4
2021-03-09
3
3
15.5
2021-03-09
1
1
12.5
2021-03-09
1
3
15.7
2021-03-09
2
2
10.6
2021-03-09
4
1
12.7
2021-03-09
4
1
12.6
Expected Result:-
BrandName
1
2
3
4
Brand-1
1
0
3
2
Brand-2
0
1
2
0
Brand-3
1
0
1
0
Need Dynamic Pivot Query
What i tried
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME([DCNo]) from [Table-B] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query = 'SELECT ' + #cols + '
from
(
SELECT a.[DCNo] , b.[BrandName], count(*) as Total FROM [Table-B] a inner join [Table-A] b on a.[ProductID]=b.[ProductID] group by [DCNo] , b.[BrandName] order by DCNo, b.[BrandName]
) x
pivot
(
max(Total)
for DCNo in (' + #cols + ')
) p '
execute(#query)

I've recreated it in a sqlfiddle: http://sqlfiddle.com/#!18/d1554/9 .
You were close but I sometimes find it easier to move all sum/count/grouping logic to the PIVOT section of the query instead. Results in simpler queries (most of the times)
CREATE TABLE [Table-A] (
ProductId INT,
BrandName VARCHAR(50)
)
CREATE TABLE [Table-B](
DCDate DATETIME,
DCNo INT,
ProductId INT,
Weight DECIMAL
)
INSERT INTO [Table-A] VALUES
(1, 'CAT'),
(2, 'APPLE'),
(3, 'PARROT')
INSERT INTO [Table-B] VALUES
('2021-03-09', 3, 1, 12.5),
('2021-03-09', 3, 1, 12.6),
('2021-03-09', 3, 1, 12.5),
('2021-03-09', 3, 2, 10.5),
('2021-03-09', 3, 2, 10.4),
('2021-03-09', 3, 3, 15.5),
('2021-03-09', 1, 1, 12.5),
('2021-03-09', 1, 3, 15.7),
('2021-03-09', 2, 2, 10.6),
('2021-03-09', 4, 1, 12.7),
('2021-03-09', 4, 1, 12.6)
-- Query
DECLARE #cols AS NVARCHAR(MAX) = '';
DECLARE #nullcols AS NVARCHAR(MAX) = '';
DECLARE #query AS NVARCHAR(MAX);
-- Determine columns
;WITH cte AS (
SELECT
DISTINCT
dcno,
',' + QUOTENAME([DCNo]) AS col,
', ISNULL(' + QUOTENAME([DCNo]) + ', 0) AS ' + QUOTENAME([DCNo]) AS nullcol
FROM [Table-B]
)
SELECT
#cols += col,
#nullcols += nullcol
FROM cte
ORDER BY dcno
SET #cols = SUBSTRING(#cols, 2, LEN(#cols))
-- create query
SET #query = N';with CTE AS
(
SELECT
a.BrandName,
a.ProductId,
b.DCNo,
1 as Value
FROM [Table-A] a
INNER JOIN [Table-B] b
ON a.ProductId = b.ProductId
)
SELECT BrandName ' + #nullcols + ' FROM
(SELECT * FROM cte) p
PIVOT
(
SUM(Value)
FOR DCNo IN (' + #cols + ')
) AS pvt
ORDER BY pvt.ProductId
'
-- SELECT #query
execute(#query)

Related

Pivot with row wise Sum in SQL Server [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
TABLE-A:
PID
BrandName
1
Brand1
2
Brand2
3
Brand3
4
Brand4
5
Brand5
6
Brand6
7
Brand7
8
Brand8
TABLE-B:
CustNo
Name
BrandName
Qty
Amt
1
C1
Brand1
3
300
1
C1
Brand2
2
400
1
C1
Brand4
1
300
1
C1
Brand5
2
100
2
C2
Brand1
2
200
2
C2
Brand3
1
200
3
C3
Brand2
1
300
3
C3
Brand7
3
150
Expected Result:-
CustNo
Name
Brand1
Brand2
Brand3
Brand4
Brand5
Brand6
Brand7
Brand8
Amt
1
C1
3
2
0
1
2
0
0
0
1100
2
C2
2
0
1
0
0
0
0
0
400
3
C3
0
1
0
0
0
0
3
0
450
Pivot I tried:-
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(BrandName) from [TABLE-A] order by PID FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query = 'SELECT CustNo,[Name],' + #cols + '
from
(
select CustNo,[Name],Qty,SUM(cast([amt] as float)) as Amt,BrandName from [TABLE-B] group by CustNo,[Name],BrandName,Qty
) x
pivot
(
max(Qty)
for brandname in (' + #cols + ')
) p '
execute(#query)
There are few things wrong in your query. First of all you selected column 'Slab' which is not in your table (might by due to copy from another query) Instead you need to select custno and name.
Then your query will run but you will have three rows for for each customer since each customer has three distinct value in quantity field. The reason behind is the group by clause (group by CustNo,[Name],BrandName,Qty) in inner query. Instead I have used window function to sum(amt) for each customer.
I have also used two set of dynamic column names to get rid of null value in the result. One to pivot as you used in your code (#cols) and other list contains coalesce(columnname,0) to convert null into 0.
And if you are using SQL Server 2017 and onward version then I would suggest to use string_agg() to concatenate the column names since it's easier and faster in performance. I have used it in Query#2.
Schema and insert statement:
create table [Table-A](PID int, BrandName varchar(50));
insert into [Table-A] values(1 ,'Brand1');
insert into [Table-A] values(2 ,'Brand2');
insert into [Table-A] values(3 ,'Brand3');
insert into [Table-A] values(4 ,'Brand4');
insert into [Table-A] values(5 ,'Brand5');
insert into [Table-A] values(6 ,'Brand6');
insert into [Table-A] values(7 ,'Brand7');
insert into [Table-A] values(8 ,'Brand8');
create table [TABLE-B]( CustNo int,Name varchar(10),BrandName varchar(50),Qty int, Amt int);
insert into [TABLE-B] values(1 ,'C1', 'Brand1', 3, 300);
insert into [TABLE-B] values(1 ,'C1', 'Brand2', 2, 400);
insert into [TABLE-B] values(1 ,'C1', 'Brand4', 1, 300);
insert into [TABLE-B] values(1 ,'C1', 'Brand5', 2, 100);
insert into [TABLE-B] values(2 ,'C2', 'Brand1', 2, 200);
insert into [TABLE-B] values(2 ,'C2', 'Brand3', 1, 200);
insert into [TABLE-B] values(3 ,'C3', 'Brand2', 1, 300);
insert into [TABLE-B] values(3 ,'C3', 'Brand7', 3, 150);
Query#1 (using stuff() and xml path for())
DECLARE #cols AS NVARCHAR(MAX),
#colsForSelect AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SET #colsForSelect = STUFF((SELECT ',' + ' Coalesce('+quotename(BrandName)+',0) '+ quotename(BrandName)
FROM [TABLE-A] order by pid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #cols = STUFF((SELECT ',' + QUOTENAME(BrandName) from [TABLE-A] order by PID FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query = 'SELECT custno,name,' + #colsForSelect + ',Amt
from
(
select CustNo,[Name],Qty,SUM(cast([amt] as float))over(partition by custno) as Amt,BrandName from [TABLE-B] ) x
pivot
(
max(Qty)
for brandname in (' + #cols + ')
) p '
execute(#query)
Output:
custno
name
Brand1
Brand2
Brand3
Brand4
Brand5
Brand6
Brand7
Brand8
Amt
1
C1
3
2
0
1
2
0
0
0
1100
2
C2
2
0
1
0
0
0
0
0
400
3
C3
0
1
0
0
0
0
3
0
450
Query#2 (using string_agg() instead of stuff() and for xml path())
DECLARE #cols AS NVARCHAR(MAX),
#colsForSelect AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #colsForSelect= string_agg('coalesce('+BrandName+',0) '+QUOTENAME(BrandName)+' ',' ,') from [TABLE-A]
select #cols = string_agg(QUOTENAME(BrandName),',') from [TABLE-A]
set #query = 'SELECT custno,name,' + #colsForSelect + ',Amt
from
(
select CustNo,[Name],Qty,SUM(cast([amt] as float))over(partition by custno) as Amt,BrandName from [TABLE-B] ) x
pivot
(
max(Qty)
for brandname in (' + #cols + ')
) p'
execute(#query)
Output:
custno
name
Brand1
Brand2
Brand3
Brand4
Brand5
Brand6
Brand7
Brand8
Amt
1
C1
3
2
0
1
2
0
0
0
1100
2
C2
2
0
1
0
0
0
0
0
400
3
C3
0
1
0
0
0
0
3
0
450
db<>fiddle here

Order by in Pivot Column not in Result

Table-A
Productid
Brandname
1
C Brand
2
K Brand
3
A Brand
Table-B
Productid
Rate
Slab
1
10
1
2
20
1
3
30
1
1
12
2
2
22
2
3
32
2
Dynamic Pivot Query:-
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Brandname) from [Table-A] FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT Slab,' + #cols + '
from
(
select a.BrandName, b.Rate,b.Slab from [Table-A] a inner join [Table-B] b on a.productid=b.productid
) x
pivot
(
max(Rate)
for Brandname in (' + #cols + ')
) p '
execute(#query)
Result:-
Slab
A Brand
C Brand
K Brand
1
30
10
20
2
32
12
22
But I need to order Brandname Column using productid
Expected Result:-
Slab
C Brand
K Brand
A Brand
1
10
20
30
2
12
22
32
While preparing column list for dynamic pivot use order by productid and remove distinct your problem will be solved.
Schema and insert statements:
create table [Table-A](Productid int,Brandname varchar(10));
insert into [Table-A] values(1 ,'C Brand');
insert into [Table-A] values(2 ,'K Brand');
insert into [Table-A] values(3 ,'A Brand');
create table [Table-B] (Productid int, Rate int , Slab int)
insert into [Table-B] values(1 ,10 ,1);
insert into [Table-B] values(2 ,20 ,1);
insert into [Table-B] values(3 ,30 ,1);
insert into [Table-B] values(1 ,12 ,2);
insert into [Table-B] values(2 ,22 ,2);
insert into [Table-B] values(3 ,32,2);
Query:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(Brandname) from [Table-A] order by productid FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT Slab,' + #cols + '
from
(
select a.BrandName, b.Rate,b.Slab from [Table-A] a inner join [Table-B] b on a.productid=b.productid
) x
pivot
(
max(Rate)
for Brandname in (' + #cols + ')
) p '
execute(#query)
Output:
Slab
C Brand
K Brand
A Brand
1
10
20
30
2
12
22
32
If you are using SQL Server 2017 or above string_agg() will be smarter and faster option.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select distinct #cols=STRING_AGG(quotename(brandname),',') from [Table-A]
set #query = 'SELECT Slab,' + #cols + '
from
(
select a.BrandName, b.Rate,b.Slab from [Table-A] a inner join [Table-B] b on a.productid=b.productid
) x
pivot
(
max(Rate)
for Brandname in (' + #cols + ')
) p '
execute(#query)
Output:
Slab
C Brand
K Brand
A Brand
1
10
20
30
2
12
22
32
db<>fiddle here
You want the columns to be in a particular order. You don't seem to need the SELECT DISTINCT in the subquery, based on your data. But if you do, you can use aggregation instead:
select #cols = STUFF((SELECT ',' + QUOTENAME(Brandname)
FROM [Table-A]
GROUP BY BrandName
ORDER BY MIN(ProductId)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'
), 1, 1, '')
However, without aggregation:
select #cols = STUFF((SELECT ',' + QUOTENAME(Brandname)
FROM [Table-A]
ORDER BY ProductId
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'
), 1, 1, '');
Once #cols is in the right order, the rest of the query should fall into place.

SQL to convert distinct item in row to column

I have a table as
Date Item Quantity
20170101 Mango 5
20170101 Orange 6
20170102 Mango 7
20170102 Orange 8
I want below output
Date Mango Orange
20170101 5 6
20170102 7 8
for this i used below sql query
SELECT
Date,
SUM(case when Item='Mango' then Quantity else 0 end) AS Mango,
SUM(case when Item='Orange' then Quantity else 0 end) AS Orange
FROM orderTable
GROUP BY date
but this is kind of hard coding for Mango and Orange. What if I need new item in orderTable. Can any one suggest me how can I make this query dynamic. So that if I add new item it automatically create new coulmn having item name as name and it will have 0 value under column against date when order not placed for that item.
like
Date Item Quantity
20170101 Mango 5
20170101 Orange 6
20170102 Mango 7
20170102 Orange 8
20170102 Cherry 9
then output should be as ...
Date Mango Orange Cherry
20170101 5 6 0
20170102 7 8 9
IF OBJECT_ID('Test') IS NOt NUll
DROP TABLE Test
CREATE TABLE Test
(
Date VARCHAR(100),
Item VARCHAR(100),
Quantity INT
)
INSERT Test VALUES
('20170101', 'Mango', 5),
('20170101', 'Orange', 6),
('20170102', 'Mango', 7),
('20170102', 'Orange', 8),
('20170102', 'Cherry', 9)
DECLARE #SQL AS VARCHAR(MAX)
DECLARE #Columns AS VARCHAR(MAX)
DECLARE #Columns2 AS VARCHAR(MAX)
SELECT #Columns = COALESCE(#Columns + ',','') + QUOTENAME(Item)
FROM (SELECT DISTINCT Item FROM Test) AS B
ORDER BY B.Item
SELECT #Columns2 = COALESCE(#Columns2 + ',','') + 'ISNULL(' + QUOTENAME(Item) + ', 0) AS ' + Item
FROM (SELECT DISTINCT Item FROM Test) AS B
ORDER BY B.Item
SET #SQL = '
WITH PivotData AS
(
SELECT Date, Item, Quantity FROM Test
)
SELECT
Date, ' + #Columns2 + '
FROM PivotData
PIVOT
(
SUM(Quantity)
FOR Item
IN (' + #Columns + ')
) AS PivotResult
ORDER BY Date'
EXEC(#SQL);
DROP TABLE Test
Result:
Date Cherry Mango Orange
20170101 0 5 6
20170102 9 7 8
Reference (code pic not shown but you can access it if you view source the page) :
http://sqlmag.com/t-sql/pivoting-dynamic-way
IF OBJECT_ID('Tempdb..#Temp') IS NOt NUll
Drop Table #Temp
;With cte([Date] ,Item ,Quantity)
AS
(
SELECT '20170101','Mango' ,5 Union all
SELECT '20170101','Orange' ,6 Union all
SELECT '20170102','Mango' ,7 Union all
SELECT '20170102','Orange' ,8 Union all
SELECT '20170102','Cherry' ,9
)
SELECT * INTO #Temp FROM cte
DECLARE #dynamicCol nvarchar(max),
#Sql nvarchar(max),
#dynamicCol2 nvarchar(max)
SELECT #dynamicCol=STUFF((SELECT DISTINCT ', ' + 'ISNULL('+Item +',''0'') AS '+ Item FROM #Temp
FOR XML PATH('')),1,1,'')
SELECT #dynamicCol2=STUFF((SELECT DISTINCT ', ' + Item FROM #Temp
FOR XML PATH('')),1,1,'')
SET #Sql='
SELECT [Date] , '+ #dynamicCol +' From
(
SELECT [Date] ,Item ,Quantity From
#temp
)AS Src
PIVOT
(
MAX([Quantity]) For [Item ] IN ('+#dynamicCol2+')
)
AS Pvt
'
PRINT #Sql
EXEC(#Sql)
OutPut
Date Cherry Mango Orange
----------------------------------
20170101 0 5 6
20170102 9 7 8
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Item)
FROM dbo.OrderTable c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT DateOrdered, ' + #cols + ' from
(
select Item, DateOrdered, Quantity
from dbo.OrderTable
) x
pivot
(
Sum(Quantity)
for Item in (' + #cols + ')
) p '
execute(#query)
If you do this it will give you result that you want
Try this :
CREATE TABLE [dbo].[test](
[Date] [int] NULL,
[Item] [nvarchar](50) NULL,
[Quantity] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170101, N'Mango', 5)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170101, N'Orange', 6)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Mango', 7)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Orange', 8)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Cherry', 5)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170103, N'Cherry', 2)
GO
dynamic sql :
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(Item)
from test
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT DATE, ' + #cols + N' from
(
select Date,Item, Quantity from test
) x
pivot
(
max(Quantity)
for Item in (' + #cols + N')
) p '
exec sp_executesql #query;
result :
DATE Cherry Mango Orange
20170101 NULL 5 6
20170102 5 7 8
20170103 2 NULL NULL

pivot in sql server 2012 with uniqeness

if i have a table like given below.
declare #mytble table
(
orders int,
product varchar (50),
quantity int
)
INSERT #mytble
SELECT 100,'CUP','1' UNION ALL
SELECT 100, 'PLATE',2 UNION ALL
SELECT 101,'CUP','1' UNION ALL
SELECT 102,'CUP','2' UNION ALL
SELECT 103, 'CUP',1 UNION ALL
SELECT 103,'PLATE','3' UNION ALL
SELECT 103,'GLASS','1'
SELECT * FROM #mytble
will it be possible to get output like this.
any suggestion please.
With some dynamic SQL and Dense_Rank() function
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName(concat('Product',Dense_Rank() over (Order By Product)))
+ ',' + QuoteName(concat('Quantity',Dense_Rank() over (Order By Product)))
From myTable For XML Path('')),1,1,'')
Select #SQL = 'Select Orders,' + #SQL + '
From (
Select Orders,Item=concat(''Product'',Dense_Rank() over (Order By Product)),Val=cast(Product as varchar(max)) From myTable
Union All
Select Orders,Item=concat(''Quantity'',Dense_Rank() over (Order By Product)),Val=cast(Quantity as varchar(max)) From myTable
) A
Pivot (max(Val) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
Orders Product1 Quantity1 Product2 Quantity2 Product3 Quantity3
100 CUP 1 NULL NULL PLATE 2
101 CUP 1 NULL NULL NULL NULL
102 CUP 2 NULL NULL NULL NULL
103 CUP 1 GLASS 1 PLATE 3

Dynamic columns not getting created in T-SQL

I have the following tables:
tblengineeringlookupcolumnmaster
elccolumnid | elclookupcode | elccolumnname | elcisrequired
1 | 64 | FirstName | 1
2 | 64 | LastName | 1
3 | 65 | abc | 1
4 | 65 | xyz | 1
tblengineeringlookupdetail
eldrecordId | eldlookupcode |eldlookupsequence |eldlookupvalue | eldlookupvaluedescription
245 | 64 | 0 | Red | Aravinth,Arumugam
246 | 64 | 1 | Blue | Santhosh,Chandran
247 | 64 | 2 | Green | Karthik,Balasubramanian
When I pass '64' as the parameter to the procedure.
I got the output as:
FirstName | LastName | eldRecordId
-------------------------------------
Aravinth | Arumugam | 245
Santhosh | Chandran | 246
Karthik | Balasubramanian| 247
The Store procedure used is
//SP
-- Select the columns to be used
DECLARE #tcol TABLE
(
ID INT IDENTITY(1,1)
, elclookupcode INT
, elccolumnname VARCHAR(100)
)
-- Insert the records into the table
INSERT INTO #tcol (elclookupcode, elccolumnname)
SELECT elclookupcode,elccolumnname FROM tblEngineeringLookupColumnMaster WHERE elclookupcode=#LookupCode
-- Select the columns which should be as output as a table
DECLARE #temp TABLE
(
elcLookupCode INT
, RecordId INT
, txt VARCHAR(8000)
)
-- Select the records from the table and insert
INSERT INTO #temp (elcLookupCode, RecordId, txt)
SELECT eldLookupCode,eldRecordId, eldLookupValueDescription FROM tblEngineeringLookupDetail WHERE eldLookupCode=#LookupCode
DECLARE #SQL NVARCHAR(MAX)
-- Have a table for the selected values
;WITH cte AS
(
SELECT
token = ', [' + d2.elccolumnname + '] = ''' + d.token + ''''
, d.RecordId
FROM (
SELECT
token = t.c.value('.', 'VARCHAR(50)')
, a.RecordId
, a.elcLookupCode
, rn = ROW_NUMBER() OVER (PARTITION BY a.RecordId ORDER BY a.RecordId)
FROM (
SELECT
RecordId
, elcLookupCode
, txml = CAST('<t>' + REPLACE(txt, ',', '</t><t>') + '</t>' AS XML)
FROM #temp
) a
CROSS APPLY txml.nodes('/t') t(c)
) d
-- Select the columns to be mapped
JOIN (
SELECT
elclookupcode
, elccolumnname
, rn = ROW_NUMBER() OVER (PARTITION BY elclookupcode ORDER BY elclookupcode)
FROM #tcol
) d2 ON d.elcLookupCode = d2.elclookupcode AND d2.rn = d.rn
)
-- Join all the records taken
SELECT #SQL = STUFF((
SELECT CHAR(13) + 'UNION ALL SELECT '+ STUFF((
SELECT t2.token
FROM cte t2
WHERE t2.RecordId = t.RecordId
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, ''), ',[RecordId] = ' + CAST(RecordId AS VARCHAR(10))
FROM #temp t
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 11, '')
PRINT #SQL
EXEC sp_executesql #SQL
END
The question now is:
If I pass '65' as parameter to the procedure,Where there are values in the first table(tblengineeringlookupcolumnmaster) and no corresponding values in the second table(tblengineeringlookupdetail) I'm getting no results( A message showing 3rows affected).
But I have to get the columns headers alone.
'Sample:
xyz | abc | eldrecordId
NULL |NULL | NULL
Why i'm not getting this? Where i'm wrong?
Try this one -
DECLARE #tcol TABLE
(
ID INT IDENTITY(1,1)
, elclookupcode INT
, elccolumnname VARCHAR(20)
)
INSERT INTO #tcol (elclookupcode, elccolumnname)
VALUES
(65, 'FirstName'),
(65, 'LastName')
DECLARE #temp TABLE
(
elcLookupCode INT
, eldRecordId INT
, txt VARCHAR(100)
)
INSERT INTO #temp (elcLookupCode, eldRecordId, txt)
VALUES
(64, 245, 'Aravinth,Arumugam'),
(64, 246, 'Santhosh,Chandran'),
(64, 247, 'Karthik,Balasubramanian')
DECLARE #SQL NVARCHAR(MAX)
;WITH cte AS
(
SELECT
token = ', [' + d2.elccolumnname + '] = ''' + d.token + ''''
, d.eldRecordId
FROM (
SELECT
token = t.c.value('.', 'VARCHAR(50)')
, a.eldRecordId
, a.elcLookupCode
, rn = ROW_NUMBER() OVER (PARTITION BY a.eldRecordId ORDER BY a.eldRecordId)
FROM (
SELECT
eldRecordId
, elcLookupCode
, txml = CAST('<t>' + REPLACE(txt, ',', '</t><t>') + '</t>' AS XML)
FROM #temp
) a
CROSS APPLY txml.nodes('/t') t(c)
) d
LEFT JOIN (
SELECT
elclookupcode
, elccolumnname
, rn = ROW_NUMBER() OVER (PARTITION BY elclookupcode ORDER BY elclookupcode)
FROM #tcol
) d2 ON d.elcLookupCode = d2.elclookupcode AND d2.rn = d.rn
)
SELECT #SQL = STUFF((
SELECT CHAR(13) + 'UNION ALL SELECT [eldRecordId] = ' + CAST(eldRecordId AS VARCHAR(10)) + ', ' +
'[elcLookupCode] = ' + CAST(elcLookupCode AS VARCHAR(10)) + ISNULL(STUFF((
SELECT t2.token
FROM cte t2
WHERE t2.eldRecordId = t.eldRecordId
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, ', '), '')
FROM #temp t
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 11, '')
PRINT #SQL
EXEC sys.sp_executesql #SQL