根据没有PIVOT的列将所有列转置为行

时间:2017-05-09 01:49:02

标签: sql-server-2008 report ssrs-2008 rdlc

我正在处理一个报告,其中所有列都需要根据列转换为行。

CREATE TABLE TempTable(
  Company VARCHAR(5), 
  ProcessDate DATETIME, 
  OpExp DECIMAL, 
  Tax DECIMAL, 
  Total DECIMAL);

INSERT INTO TempTable VALUES
('Comp1', getdate(), 1000, 100, 1100),
('Comp1', dateadd(year, -1, getdate()), 2000, 200, 2200),
('Comp1', dateadd(year, -2, getdate()), 3000, 300, 3300);

SELECT * FROM TempTable;

enter image description here

但是对于报告,我必须将此表转换为

enter image description here

此处2015,2016,2017栏是动态的,基于'ProcessDate'年。

我尝试使用PIVOT,但它会抛出

Incorrect syntax near 'PIVOT'. You may need to set the compatibility level of the current database to a higher value to enable this feature. See help for the SET COMPATIBILITY_LEVEL option of ALTER DATABASE

由于数据库已经投入生产,因此无法更改 兼容性水平。

我按照

中的建议尝试使用UNION ALL,CASE

Simple way to transpose columns and rows in Sql?

但是列数据类型不同,不能使用聚合函数,因为结果必须包含所有行。

有没有办法将列转换为行?或者是否可以使用SSRS而不是RDLC生成此报告?

2 个答案:

答案 0 :(得分:0)

注意:您可以更改兼容级别。只要您将兼容级别更改为更高的值并且您没有依赖此数据库的链接服务器等处于该特定版本,它就不会影响任何内容。显然,如果您不确定,请不要触摸它

无论如何,有几种方法可以做到这一点。这种方法使用UNION,我不确定你为什么说你不能使用这种方法,但这确实给出了样本期望的样子。

DECLARE @Temptable TABLE (
  Company VARCHAR(5), 
  ProcessDate DATETIME, 
  OpExp DECIMAL, 
  Tax DECIMAL, 
  Total DECIMAL);

INSERT INTO @TempTable VALUES
('Comp1', getdate(), 1000, 100, 1100),
('Comp1', dateadd(year, -1, getdate()), 2000, 200, 2200),
('Comp1', dateadd(year, -2, getdate()), 3000, 300, 3300);

SELECT * FROM @TempTable

DECLARE @ReportStartYear int = 2017

SELECT 
    t.Company
    , 'OpExp' as Val
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear -2 THEN OpExp ELSE 0 END) AS ColA
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear -1 THEN OpExp ELSE 0 END) AS ColB
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear  THEN OpExp ELSE 0 END) AS ColC
    , @ReportStartYear - 2 as ColACaption
    , @ReportStartYear - 1 as ColBCaption
    , @ReportStartYear  as ColCCaption
    FROM @Temptable t
    GROUP BY t.Company
UNION ALL
SELECT 
    t.Company
    , 'Tax' as Val
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear -2 THEN Tax ELSE 0 END) AS ColA
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear -1 THEN Tax ELSE 0 END) AS ColB
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear  THEN Tax ELSE 0 END) AS ColC
    , @ReportStartYear - 2 as ColACaption
    , @ReportStartYear - 1 as ColBCaption
    , @ReportStartYear  as ColCCaption
    FROM @Temptable t
    GROUP BY t.Company
UNION ALL
SELECT 
    t.Company
    , 'Total' as Val
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear -2 THEN Total ELSE 0 END) AS ColA
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear -1 THEN Total ELSE 0 END) AS ColB
    , SUM(CASE YEAR(t.ProcessDate) WHEN @ReportStartYear  THEN Total ELSE 0 END) AS ColC
    , @ReportStartYear - 2 as ColACaption
    , @ReportStartYear - 1 as ColBCaption
    , @ReportStartYear  as ColCCaption
    FROM @Temptable t
    GROUP BY t.Company

返回以下内容

Company Val     ColA    ColB    ColC    ColACaption ColBCaption ColCCaption
Comp1   OpExp   3000    2000    1000    2015        2016        2017
Comp1   Tax     300     200     100     2015        2016        2017
Comp1   Total   3300    2200    1100    2015        2016        2017

在报告中,您可以将列标题设置为=FIRST(Fields!ColACaption.Value)等,这样您就不必担心列名称是动态的。 如果您知道将返回多少列,则此方法有效。

HOWEVER 如果在SSRS中执行此操作可能更容易。创建一个矩阵,将列组设置为返回ProcessDate列的YEAR的表达式,然后在每个值类型(OpExp,Tax& Total)的详细信息组中添加一行,这应该给你什么也希望不需要更改任何SQL。

答案 1 :(得分:0)

这是SSRS的唯一方式,这可能是最好的方法......

我在这个示例中稍微扩展了您的示例数据,包括9行,3行公司的3行。

创建新的空白报告并正常添加数据集。 然后在报表上插入矩阵控件。 拖动字段,如下图所示,以初始设置矩阵。我们将对此进行编辑,但它可以让我们快速入手。

注意:第3步应为“在此处拖动ProcessDate ...” enter image description here

现在我们需要从流程日期到年份,因此右键单击步骤3中的ProcessDate单元格并单击“表达式”。将表达式设置为

=YEAR(Fields!ProcessDate.Value)

在组设计器窗格的报表设计下,右键单击[ProcessDate]列组并选择“组属性”,并将Group On属性设置为相同的表达式=YEAR(Fields!ProcessDate.Value) {{3} }

现在回到报告设计中,右键单击数据单元格(从上面的步骤4开始)并执行'Insert Row' - > '内部小组 - 低于'enter image description here

重复此过程以添加第3行。

在两个新的空白单元格中,单击字段列表下拉列表,然后分别选择“税收”和“总计”。

enter image description here

如果要添加标题列。右键单击其中包含[公司]的单元格,执行“插入列” - > 'Inside Group - Right',然后右键单击新单元格并选择'split cell',这将取消合并3行。然后,您可以为每行键入标题。 设计现在应该是这样的。

enter image description here

这就是它......

最终输出如下所示。

enter image description here