SQL 数据透视问题,请引用下表(注意年份和月份是分开的):
CREATE TABLE [dbo].[tbl_BranchTargets]
(
[BranchID] [varchar](4) NOT NULL ,
[Year] [smallint] NOT NULL ,
[Month] [smallint] NOT NULL ,
[Target] [int] NULL ,
CONSTRAINT [PK_tbl_BranchTargets] PRIMARY KEY CLUSTERED ( [BranchID] ASC, [Year] ASC, [Month] ASC ) WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
)
ON [PRIMARY]
以及以下虚拟数据:
INSERT [dbo].[tbl_BranchTargets] ([BranchID], [Year], [Month], [Target]) VALUES (N'001', 2012, 4, 1)
INSERT [dbo].[tbl_BranchTargets] ([BranchID], [Year], [Month], [Target]) VALUES (N'001', 2012, 5, 117)
INSERT [dbo].[tbl_BranchTargets] ([BranchID], [Year], [Month], [Target]) VALUES (N'001', 2012, 6, 233)
INSERT [dbo].[tbl_BranchTargets] ([BranchID], [Year], [Month], [Target]) VALUES (N'001', 2012, 7, 386)
INSERT [dbo].[tbl_BranchTargets] ([BranchID], [Year], [Month], [Target]) VALUES (N'003', 2012, 4, 2)
INSERT [dbo].[tbl_BranchTargets] ([BranchID], [Year], [Month], [Target]) VALUES (N'003', 2012, 6, 234)
INSERT [dbo].[tbl_BranchTargets] ([BranchID], [Year], [Month], [Target]) VALUES (N'003', 2012, 7, 387)
我如何对给定的虚拟数据进行建模(请注意,年份和月份键列被合并以形成 YYYYMM):
进入此:
请注意 5 月份分支 3 缺少条目,需要将其处理为 null。例如,在 12 个月中,分支可能只有其中 1 个月的目标,因此所有其他月份都需要为空。
我研究了 PIVOT() 和笨重的游标选项,但我正在努力寻找一种快速的最佳实践方法,我假设我需要实现一些动态 SQL + PIVOT() - 但不能完全让我明白这一点。
我知道对于动态数据透视,您首先要确定列名称(我认为),我可以按如下方式执行此操作:
DECLARE @Columns AS NVARCHAR(MAX);
DECLARE @StrSQL AS NVARCHAR(MAX);
SET @Columns = STUFF((SELECT DISTINCT
',' + QUOTENAME(CONVERT(VARCHAR, c.YEAR) + RIGHT('00' + CONVERT(VARCHAR, c.MONTH), 2))
FROM tbl_BranchTargets c
FOR XML PATH('') ,
TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
但是如何执行数据透视有点超出了我的范围(因为我本质上是合并到关键列以创建最终列)-我是否需要在尝试数据透视之前合并数据,其中 YYYY + MM 被定义为值在 1 列中?
(我使用的是 SQL Server 2008 R2)
最佳答案
您已经非常接近最终答案了。您可以使用 PIVOT
类似于以下内容(请参阅 SQL Fiddle with Demo ):
DECLARE @Columns AS NVARCHAR(MAX)
DECLARE @StrSQL AS NVARCHAR(MAX)
SET @Columns = STUFF((SELECT DISTINCT
',' + QUOTENAME(CONVERT(VARCHAR(4), c.YEAR) + RIGHT('00' + CONVERT(VARCHAR(2), c.MONTH), 2))
FROM tbl_BranchTargets c
FOR XML PATH('') ,
TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
set @StrSQL = 'SELECT branchid, ' + @Columns + ' from
(
select branchid
, target
, CONVERT(VARCHAR(4), [YEAR]) + RIGHT(''00'' + CONVERT(VARCHAR(2), [MONTH]), 2) dt
from tbl_BranchTargets
) x
pivot
(
sum(target)
for dt in (' + @Columns + ')
) p '
execute(@StrSQL)
这将创建您在执行时所需的列列表。
关于SQL Pivot 具有不同数量的行和复合键来形成列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11742415/