我具有以下表格格式:
我需要将此表转换为以下格式:
我在其他问题中查找了PIVOT函数,但是输入表中的“键”值不是一组固定值,它们可以是任何值。我也在寻找其他类似的问题,但我不确定该如何编写查询。
我的代码是:
SELECT
ROW_NUMBER () OVER (
ORDER BY RouteCode) AS SrNo
, RouteCode AS X
, SUM(Units) AS Y
FROM
[ INTERFACE_ok ] .[ dbo ] .[ v_A40OrdersBhQt ]
WHERE [ DeliveryDate ] > CAST(
FLOOR(CAST(GETDATE () AS FLOAT)) AS DATETIME
)
AND CustomerCode LIKE '900%'
GROUP BY [ RouteCode ]
任何帮助将不胜感激,谢谢!
答案 0 :(得分:3)
您正在寻找动态枢纽。
主要步骤如下
@sqlX
和@sqlY
以携带您的MAX
函数和CASW WHEN
表达式以创建X
和Y
枢轴列号。CONCAT
组合您的SUM函数和CASW WHEN表达式字符串和主选择字符串以及UNION ALL
@sqlX
和@sqlY
查询字符串。EXECUTE
函数动态执行SQL。TestDLL
CREATE TABLE T(
SrNo INT,
X VARCHAR(100),
Y INT
);
INSERT INTO T VALUES (1,'N1',100);
INSERT INTO T VALUES (2,'N2',200);
INSERT INTO T VALUES (3,'N3',300);
INSERT INTO T VALUES (4,'N4',400);
INSERT INTO T VALUES (5,'N5',500);
INSERT INTO T VALUES (6,'N6',600);
INSERT INTO T VALUES (7,'N7',700);
这是mysql示例。
SET @sqlX = NULL;
SET @sqlY = NULL;
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN SrNo =',
SrNo,
' THEN X END) '
)
) INTO @sqlX
FROM T;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(CASE WHEN SrNo =',
SrNo,
' THEN Y END) '
)
) INTO @sqlY
FROM T;
SET @sql = CONCAT('SELECT ''X'', ', @sqlX, '
FROM T
UNION ALL
SELECT ''Y'', ', @sqlY, '
FROM T
');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SQL-Server版本
DECLARE @sqlX VARCHAR(MAX)
DECLARE @sqlY VARCHAR(MAX)
DECLARE @sql VARCHAR(MAX)
SET @sqlX = STUFF((SELECT distinct ', CAST( MAX(CASE WHEN SrNo =' + CAST(SrNo AS VARCHAR(5)) + ' THEN X END) AS VARCHAR(MAX)) '
FROM T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET @sqlY = STUFF((SELECT distinct ',CAST( MAX(CASE WHEN SrNo = ' + CAST(SrNo AS VARCHAR(5)) + ' THEN Y END) AS VARCHAR(MAX)) '
FROM T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
set @sql = CONCAT('SELECT ''X'', ', @sqlX, '
FROM T
UNION ALL
SELECT ''Y'', ', @sqlY, '
FROM T');
execute(@sql)
结果
| X | MAX(CASE WHEN SrNo =1 THEN X END) | MAX(CASE WHEN SrNo =2 THEN X END) | MAX(CASE WHEN SrNo =3 THEN X END) | MAX(CASE WHEN SrNo =4 THEN X END) | MAX(CASE WHEN SrNo =5 THEN X END) | MAX(CASE WHEN SrNo =6 THEN X END) | MAX(CASE WHEN SrNo =7 THEN X END) |
|---|-----------------------------------|-----------------------------------|-----------------------------------|-----------------------------------|-----------------------------------|-----------------------------------|-----------------------------------|
| X | N1 | N2 | N3 | N4 | N5 | N6 | N7 |
| Y | 100 | 200 | 300 | 400 | 500 | 600 | 700 |
注意:
T
可以代替您的子查询或当前结果集。
答案 1 :(得分:1)
亚伦·伯特兰(Aaron Bertrand)写了一篇适合您需要的文章: https://www.mssqltips.com/sqlservertip/2783/script-to-create-dynamic-pivot-queries-in-sql-server/
USE tempdb;
GO
CREATE TABLE dbo.Products
(
ProductID INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL UNIQUE
/* other columns */
);
INSERT dbo.Products VALUES
(1, N'foo'),
(2, N'bar'),
(3, N'kin');
CREATE TABLE dbo.OrderDetails
(
OrderID INT,
ProductID INT NOT NULL
FOREIGN KEY REFERENCES dbo.Products(ProductID),
Quantity INT
/* other columns */
);
INSERT dbo.OrderDetails VALUES
(1, 1, 1),
(1, 2, 2),
(2, 1, 1),
(3, 3, 1);
他的动态解决方案是将一些东西应用于PIVOT语句:
编写一个收集列的子查询:
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns += N', p.' + QUOTENAME(Name)
FROM (SELECT p.Name FROM dbo.Products AS p
INNER JOIN dbo.OrderDetails AS o
ON p.ProductID = o.ProductID
GROUP BY p.Name) AS x;
然后创建您的可执行SQL:
SET @sql = N'
SELECT ' + STUFF(@columns, 1, 2, '') + '
FROM
(
SELECT p.Name, o.Quantity
FROM dbo.Products AS p
INNER JOIN dbo.OrderDetails AS o
ON p.ProductID = o.ProductID
) AS j
PIVOT
(
SUM(Quantity) FOR Name IN ('
+ STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
PRINT @sql;
最后运行它:
EXEC sp_executesql @sql;