动态列-SQL Server-月份作为列
数据库:SQL Server 2005 我们有一个以这种方式包含数据的表:动态列-SQL Server-月份作为列,sql,sql-server,sql-server-2005,tsql,ssis,Sql,Sql Server,Sql Server 2005,Tsql,Ssis,数据库:SQL Server 2005 我们有一个以这种方式包含数据的表: Project Year Jan Feb Mar Apr May Jun Jul Aug Sep
Project Year Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
-------------------- ----------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- --------------------- ---------------------
11-11079 2008 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 75244.90
11-11079 2009 466.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
11-11079 2010 855.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
01-11052 2009 56131.00 0.00 36962.00 -61596.00 2428.00 84.00 0.00 0.00 0.00 0.00 0.00 0.00
有人希望数据显示为整个项目的一行。这些列将是动态的,这取决于未来的年数。例如:
Project Jan-2009 Feb-2009 Mar-2009 Apr-2009... Dec-2009 Jan-2010
-------------- ------------ ------------ ------------ ----------- ------------ ---------
11-11079 466.00 0.00 0.00 0.00 0.00 855.00
01-11052 56131.00 0.00 36962.00 -61596.00 2428.00 0.00
我读过很多例子,其中每个条目的日期填充在一列中,但我没有发现任何以月份为列名、以年份为行的情况
具有透视表的动态SQL?或者使用SQL、临时表、联接和联合进行大规模操作?
关于使用SSIS透视表功能有什么想法吗?我认为可以使用嵌套的while循环和一些动态SQL来实现。如果无法保存最终表,或者必须每月重新生成所有列,那么这将是一个缓慢的解决方案。然而,如果它只是一个加法,那么它可能并不坏。无论如何,我会这样做:
您的数据已进行数据透视,但需要在不同级别进行数据透视。我认为处理这个问题的最好方法是先取消pivot,然后再处理正确的pivot级别 步骤1:取消PIVOT 您可以使用SQL2005命令,也可以使用交叉连接技术。这里有两个例子。注意我在中间放了几个月让事情变得简单。把它们加进去就行了
-- CROSS JOIN method (also works in SQL 2000)
SELECT
P.Project,
Mo =
DateAdd(mm,
X.MonthNum,
DateAdd(yy, P.[Year] - 1900, '19000101')
),
Amount =
CASE X.MonthNum
WHEN 0 THEN Jan
WHEN 1 THEN Feb
WHEN 11 THEN Dec
END
FROM
ProjectData P
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 11
) X (MonthNum)
每行重复12次,然后CASE语句只为每行提取一个月的数据,使数据很好地未插入
-- UNPIVOT method
SELECT
P.Project,
Mo =
DateAdd(mm,
Convert(int, P.MonthNum),
DateAdd(yy, P.[Year] - 1900, '19000101')
),
P.Amount
FROM
(
SELECT Project, [Year], [0] = Jan, [1] = Feb, [11] = Dec
FROM ProjectData
) X UNPIVOT (Amount FOR MonthNum IN ([0], [1], [11])) P
DROP TABLE ProjectData
这两种方法都不是一直以来的性能赢家。有时一个比另一个工作得更好(取决于数据透视)。UNPIVOT方法在执行计划中使用交叉联接不使用的筛选器
第2步:再次旋转
现在,如何使用未插入的数据。您没有说您的某人将如何使用这些数据,但由于您需要将数据放入某种输出文件中,因此我建议使用Sql Server 2005附带的SSRS(Sql Server Reporting Services),无需额外收费
只需使用报表对象来透视上面的一个查询。这个对象很高兴地确定了要在报表运行时生成列标签的数据值,听起来正是您所需要的。如果添加的列格式与您喜欢的日期格式完全一致,则可以按Mo列排序,但可以使用新表达式作为列标签
SSRS还提供多种格式和调度选项。例如,您可以让它通过电子邮件发送Excel文件或将网页保存到文件共享
如果我遗漏了什么,请告诉我
对于希望看到上述代码实际运行的任何人,这里有一些创建脚本供您使用:
USE tempdb
CREATE TABLE ProjectData (
Project varchar(10),
[Year] int,
Jan decimal(15, 2),
Feb decimal(15, 2),
Dec decimal(15, 2)
)
SET NOCOUNT ON
INSERT ProjectData VALUES ('11-11079', 2008, 0.0, 0.0, 75244.90)
INSERT ProjectData VALUES ('11-11079', 2009, 466.0, 0.0, 0.0)
INSERT ProjectData VALUES ('11-11079', 2010, 855.0, 0.0, 0.0)
INSERT ProjectData VALUES ('01-11052', 2009, 56131.0, 0.0, 0.0)
我编写了一个名为pivot\u query的存储过程,它可以帮助解决这个问题,源代码是,原始数据示例
不精确,但非常接近。:-) 请不要在标题或问题中使用术语“MS SQL”。没有这样的产品。使用它会使搜索很难找到您的问题,并且会混淆SQL Server和MySQL之间的关系。嘿-我忽略了我知道答案的tsql问题,因为我将MSSQL理解为MySQLJohn-这些名称很接近,也很混乱,但公平地说,在这里发布的人,Microsoft SQL Server在某种程度上被称为MSSQL。请查看二进制文件的路径:-)C:\Program Files\Microsoft SQL Server\MSSQLS10.TEST2008\MSSQL或PowerShell>Get Service,至少对我来说,它会生成MSSQL$TEST2008作为服务的名称。@OnUpdate Cascade:文件夹的名称与产品的名称不相等。我也不是在责怪他们或其他什么——我是在解释为什么不在这里使用这个词。我想如果你能说
SQL Server
是一个非常糟糕的SQL Server名称,不管它多么贴切MSSQL
当然更具描述性,并将排除其他内容(如本消歧页上列出的内容:)。更不用说它有这种傲慢的权威声音,不能很好地代表产品或竞争对手的替代品。很抱歉,RandomBen,当基于集合的解决方案清晰易用,可用于取消激励,然后再次旋转时,根本不支持循环。循环的性能将非常糟糕。我忘了添加5月份,但不允许我编辑帖子以将其放入。:-)天哪,罗恩。当基于集合的代码和现有SQL Server工具可以解决问题时,为什么还要使用大量的过程代码?它是通用的,适用于任何查询,而不必知道数据透视列的值。在许多“数据透视”样式的报告中为我们节省了大量开发人员时间。我不是为了这个才写的。:-)@罗恩·萨维奇:罗恩,我也有类似的代码,我花了很多时间在一些更通用的程序代码上,以解决重复出现的问题。然而。。。SSRS矩阵报表控件也是“通用的,可以用于任何查询,而不必知道数据透视列的值。”既然你说你是为报表而做的,我无法想象为什么当SSR可以开箱即用时,有人会想使用过程代码。不是我们所有的应用程序都可以访问或需要使用报表服务器。我们也有使用矩阵的报表,并且我们发现,对于旋转大型结果集,此过程要快得多,因为只有汇总的结果发送到报表服务器,而不是控件要旋转和汇总的所有原始数据。我不知道你为什么打电话来
With your data:
create table ProjectData
(
Project varchar(20),
[Year] Integer,
Jan decimal(12,2),
Feb decimal(12,2),
Mar decimal(12,2),
Apr decimal(12,2),
May decimal(12,2),
Jun decimal(12,2),
Jul decimal(12,2),
Aug decimal(12,2),
Sep decimal(12,2),
Oct decimal(12,2),
Nov decimal(12,2),
Dec decimal(12,2)
);
insert into ProjectData values ('11-11079',2008, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 75244.90);
insert into ProjectData values ('11-11079',2009, 466.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00);
insert into ProjectData values ('11-11079',2010, 855.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00) ;
insert into ProjectData values ('01-11052',2009, 56131.00, 0.00, 36962.00, -61596.00, 2428.00, 84.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00);
declare @mySQL varchar(MAX)
set @mySQL = 'select * from ProjectData'
exec pivot_query @mySQL, 'Project', 'Year', 'max(Jan) Jan,max(Feb) Feb,max(Mar) Mar,max(Apr) Apr,max(Jun) Jun,max(Jul) Jul,max(Aug) Aug,max(Sep) Sep,max(Oct) Oct,max(Nov) Nov,max(Dec) Dec'
Results:
Project 2008_Jan 2008_Feb 2008_Mar 2008_Apr 2008_Jun 2008_Jul 2008_Aug 2008_Sep 2008_Oct 2008_Nov 2008_Dec 2009_Jan 2009_Feb 2009_Mar 2009_Apr 2009_Jun 2009_Jul 2009_Aug 2009_Sep 2009_Oct 2009_Nov 2009_Dec 2010_Jan 2010_Feb 2010_Mar 2010_Apr 2010_Jun 2010_Jul 2010_Aug 2010_Sep 2010_Oct 2010_Nov 2010_Dec
-------------------- ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------
01-11052 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 56131.00 .00 36962.00 -61596.00 84.00 .00 .00 .00 .00 .00 .00 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
11-11079 .00 .00 .00 .00 .00 .00 .00 .00 .00 .00 75244.90 466.00 .00 .00 .00 .00 .00 .00 .00 .00 .00 .00 855.00 .00 .00 .00 .00 .00 .00 .00 .00 .00 .00