我有一个看起来像这样的表架构
CREATE TABLE [dbo].[Discounts]( [Id] [int] NOT NULL, [ProductId] [varchar(50)] NOT NULL, [LowerBoundDays] [int] NOT NULL, [UpperBoundDays] [int] NOT NULL, [Discount] [decimal](18, 4) NOT NULL,
还有一些这样的数据
lower upper discount(%) product1 0 10 0 product1 10 30 1 product1 30 60 2 product1 60 90 3 product1 90 120 4 product2 0 10 0 product2 10 30 1 product2 30 60 2 product2 60 90 3 product2 90 120 4
如何执行数据透视查询以获取如下所示的2行:
0-10 10-30 30-60 60-90 90-120 product1 0 1 2 3 4 product2 0 1 2 3 4
由于使用的是SQL Server,因此有几种方法可以将数据行转换为列。
您可以将聚合函数与CASE表达式一起使用以获取结果:
select productid, max(case when lower = 0 and upper = 10 then discount end) [0-10], max(case when lower = 10 and upper = 30 then discount end) [10-30], max(case when lower = 30 and upper = 60 then discount end) [30-60], max(case when lower = 60 and upper = 90 then discount end) [60-90], max(case when lower = 90 and upper = 120 then discount end) [90-120] from CorporateSpread group by productid;
如果使用的是SQL Server 2005+,则可以使用PIVOT函数:
select productid, [0-10], [10-30], [30-60], [60-90],[90-120] from ( select productid, discount, cast(lower as varchar(10)) + '-' + cast(upper as varchar(10)) rng from CorporateSpread ) d pivot ( max(discount) for rng in ([0-10], [10-30], [30-60], [60-90],[90-120]) ) piv;
如果值的数量已知,则上面的两个版本非常有用,但是如果范围的数量未知,那么您将需要使用动态SQL:
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX) select @cols = STUFF((SELECT distinct ',' + QUOTENAME(cast(lower as varchar(10)) + '-' + cast(upper as varchar(10))) from CorporateSpread FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') set @query = 'SELECT productid, ' + @cols + ' from ( select productid, discount, cast(lower as varchar(10)) + ''-'' + cast(upper as varchar(10)) rng from CorporateSpread ) x pivot ( max(discount) for rng in (' + @cols + ') ) p ' execute sp_executesql @query;
请参阅带有演示的SQL Fiddle。所有版本都会产生结果:
| PRODUCTID | 0-10 | 10-30 | 30-60 | 60-90 | 90-120 | ----------------------------------------------------- | product1 | 0 | 1 | 2 | 3 | 4 | | product2 | 0 | 1 | 2 | 3 | 4 |