在 SQL Server 中,数据透视查询通常使用 PIVOT
操作符来实现。然而,PIVOT
操作符通常需要聚合函数来汇总数据。如果你想在不使用聚合函数的情况下进行数据透视,可以使用条件聚合(conditional aggregation)来实现。
假设你有一个表 Sales
,其结构如下:
CREATE TABLE Sales (
SalesPerson NVARCHAR(50),
Product NVARCHAR(50),
Amount INT
);
INSERT INTO Sales (SalesPerson, Product, Amount) VALUES
('Alice', 'ProductA', 100),
('Alice', 'ProductB', 150),
('Bob', 'ProductA', 200),
('Bob', 'ProductC', 250);
你希望将数据透视,使每个销售人员的销售额按产品列出,而不使用聚合函数。可以使用条件聚合来实现这一点:
SELECT
SalesPerson,
MAX(CASE WHEN Product = 'ProductA' THEN Amount ELSE NULL END) AS ProductA,
MAX(CASE WHEN Product = 'ProductB' THEN Amount ELSE NULL END) AS ProductB,
MAX(CASE WHEN Product = 'ProductC' THEN Amount ELSE NULL END) AS ProductC
FROM Sales
GROUP BY SalesPerson;
CASE
表达式来检查每一行的 Product
列。Product
列的值匹配特定产品(如 'ProductA'),则返回 Amount
列的值,否则返回 NULL
。MAX
函数在这里不会实际进行聚合,而是简单地返回该值。SalesPerson
分组,以确保每个销售人员只有一行。上述查询将返回以下结果:
SalesPerson | ProductA | ProductB | ProductC |
---|---|---|---|
Alice | 100 | 150 | NULL |
Bob | 200 | NULL | 250 |
如果产品列是动态的(即你不知道有多少种产品),你可以使用动态 SQL 来生成查询。以下是一个示例:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
-- 获取所有产品的列名
SELECT @cols = STRING_AGG(QUOTENAME(Product), ',')
FROM (SELECT DISTINCT Product FROM Sales) AS Products;
-- 构建动态 SQL 查询
SET @query = '
SELECT SalesPerson, ' + @cols + '
FROM (
SELECT SalesPerson, Product, Amount
FROM Sales
) AS SourceTable
PIVOT (
MAX(Amount)
FOR Product IN (' + @cols + ')
) AS PivotTable
ORDER BY SalesPerson';
-- 执行动态 SQL 查询
EXEC sp_executesql @query;
STRING_AGG
函数获取所有产品的列名,并用逗号分隔。PIVOT
操作符和 MAX
函数来生成透视表。sp_executesql
存储过程执行动态 SQL 查询。领取专属 10元无门槛券
手把手带您无忧上云