Dynamic Pivot Sql 查询显示全部来自一个 table
Dynamic Pivot Sql Query display all from one table
TABLE-A:-
Custno
Name
Route
Phone
1
C1
1
12345
2
C2
1
23456
3
C3
2
34567
4
C4
1
45678
5
C5
1
56789
TABLE-B:-
ODate
Custno
Route
ProductId
qty
2021-04-22
1
1
1
100
2021-04-22
1
1
3
200
2021-04-22
2
1
1
120
Table-C
ProductId
BrandName
1
Brand-1
2
Brand-2
3
Brand-3
预期结果
Phone
CustNo
Name
Brand-1
Brand-2
Brand-3
12345
1
C1
100
200
23456
2
C2
120
45678
4
C4
56789
5
C5
我尝试使用 Dynamic Pivot
DECLARE @query AS VARCHAR(MAX)
, @cols_ AS vARCHAR(MAX)
--Making the column list dynamically
select @cols_ = STUFF((SELECT ',' + QUOTENAME(brandname) from [Table-C] order by productid FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
print @cols_
--preparing PIVOT query dynamically.
SET @query = ' SELECT
pivoted.*
into #Temp_data
FROM
(
select a.phone,a.custno,a.[name],d.BrandName,c.qty from [Table-A] a inner join [Table-B] c on a.custno = c.custno inner join [Table-C] d on c.productid = d.Productid and a.Route='1' and c.odate='2021-04-22'
) AS [p]
PIVOT
(
MIN([P].[qty])
FOR [P].[BrandName] IN (' + @cols_ + ')
) AS pivoted
order by custno;
select *
from #Temp_data [B]
-- GROUP BY [B].[ODate]
drop table #Temp_data
';
EXEC (@query)
您可以重建查询
SELECT *
FROM
(
SELECT A.[Phone], A.[CustNo], A.[Name], C.[BrandName], B.[qty]
FROM [Table-A] AS A
LEFT JOIN [Table-B] AS B
ON A.[CustNo] = B.[CustNo]
AND B.[odate] = '2021-04-22'
LEFT JOIN [Table-C] AS C on C.productid = B.Productid
WHERE A.[Route] = 1
) t
PIVOT
(
MIN([qty]) FOR [BrandName] IN ([Brand-1],[Brand-2],[Brand-3])
) AS piv
其中包含 LEFT JOIN
而不是 INNER JOIN
,以及 STRING_AGG()
函数以便动态生成旋转列,如以下代码块
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SET @cols = ( SELECT STRING_AGG(QUOTENAME([BrandName]),',')
FROM (SELECT DISTINCT [BrandName]
FROM [Table-C] ) C );
SET @query =
N'SELECT *
FROM
(
SELECT A.[Phone], A.[CustNo], A.[Name], C.[BrandName], B.[qty]
FROM [Table-A] AS A
LEFT JOIN [Table-B] AS B
ON A.[CustNo] = B.[CustNo]
AND B.[odate] = ''2021-04-22''
LEFT JOIN [Table-C] AS C on C.productid = B.Productid
WHERE A.[Route] = 1
) t
PIVOT
(
MIN([qty]) FOR [BrandName] IN (' + @cols + N')
) AS piv'
EXEC sp_executesql @query;
TABLE-A:-
Custno | Name | Route | Phone |
---|---|---|---|
1 | C1 | 1 | 12345 |
2 | C2 | 1 | 23456 |
3 | C3 | 2 | 34567 |
4 | C4 | 1 | 45678 |
5 | C5 | 1 | 56789 |
TABLE-B:-
ODate | Custno | Route | ProductId | qty |
---|---|---|---|---|
2021-04-22 | 1 | 1 | 1 | 100 |
2021-04-22 | 1 | 1 | 3 | 200 |
2021-04-22 | 2 | 1 | 1 | 120 |
Table-C
ProductId | BrandName |
---|---|
1 | Brand-1 |
2 | Brand-2 |
3 | Brand-3 |
预期结果
Phone | CustNo | Name | Brand-1 | Brand-2 | Brand-3 |
---|---|---|---|---|---|
12345 | 1 | C1 | 100 | 200 | |
23456 | 2 | C2 | 120 | ||
45678 | 4 | C4 | |||
56789 | 5 | C5 |
我尝试使用 Dynamic Pivot
DECLARE @query AS VARCHAR(MAX)
, @cols_ AS vARCHAR(MAX)
--Making the column list dynamically
select @cols_ = STUFF((SELECT ',' + QUOTENAME(brandname) from [Table-C] order by productid FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
print @cols_
--preparing PIVOT query dynamically.
SET @query = ' SELECT
pivoted.*
into #Temp_data
FROM
(
select a.phone,a.custno,a.[name],d.BrandName,c.qty from [Table-A] a inner join [Table-B] c on a.custno = c.custno inner join [Table-C] d on c.productid = d.Productid and a.Route='1' and c.odate='2021-04-22'
) AS [p]
PIVOT
(
MIN([P].[qty])
FOR [P].[BrandName] IN (' + @cols_ + ')
) AS pivoted
order by custno;
select *
from #Temp_data [B]
-- GROUP BY [B].[ODate]
drop table #Temp_data
';
EXEC (@query)
您可以重建查询
SELECT *
FROM
(
SELECT A.[Phone], A.[CustNo], A.[Name], C.[BrandName], B.[qty]
FROM [Table-A] AS A
LEFT JOIN [Table-B] AS B
ON A.[CustNo] = B.[CustNo]
AND B.[odate] = '2021-04-22'
LEFT JOIN [Table-C] AS C on C.productid = B.Productid
WHERE A.[Route] = 1
) t
PIVOT
(
MIN([qty]) FOR [BrandName] IN ([Brand-1],[Brand-2],[Brand-3])
) AS piv
其中包含 LEFT JOIN
而不是 INNER JOIN
,以及 STRING_AGG()
函数以便动态生成旋转列,如以下代码块
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)
SET @cols = ( SELECT STRING_AGG(QUOTENAME([BrandName]),',')
FROM (SELECT DISTINCT [BrandName]
FROM [Table-C] ) C );
SET @query =
N'SELECT *
FROM
(
SELECT A.[Phone], A.[CustNo], A.[Name], C.[BrandName], B.[qty]
FROM [Table-A] AS A
LEFT JOIN [Table-B] AS B
ON A.[CustNo] = B.[CustNo]
AND B.[odate] = ''2021-04-22''
LEFT JOIN [Table-C] AS C on C.productid = B.Productid
WHERE A.[Route] = 1
) t
PIVOT
(
MIN([qty]) FOR [BrandName] IN (' + @cols + N')
) AS piv'
EXEC sp_executesql @query;