【问题标题】:Can I make a tablix report in SSRS from dynamically pivoted table?我可以从动态数据透视表在 SSRS 中制作 tablix 报告吗?
【发布时间】:2017-09-14 17:01:29
【问题描述】:

我的查询结果是显示从当前月份开始的 12 个月前的数据透视表和总金额。月份是动态的,因此在 10 月,表格中的第一列将是 11 月,最后一列将是 10 月(当前)。

如何使用此结果集创建简单的 tablix 或矩阵?我主要关心的是如何在 tablix 中制作动态月份名称?

这可能吗?

更新:

我将列重命名为从 1 到 12 的值。但是当我尝试从 10 月编写一个表达式时,例如:=Month(Today()) - CInt(Fields!ID10.Value) 它只是给了我当前月份的编号。 我错过了什么?

更新: 表 Calendar 中的数据结构如下:

所以我修改了查询:

  DECLARE @CurrentMonth DATE = DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '19000101');
--print @CurrentMonth

SELECT 
    M_00 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 0 THEN 1 END),
    M_01 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 1 THEN 1 END),
    M_02 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 2 THEN 1 END),
    M_03 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 3 THEN 1 END),
    M_04 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 4 THEN 1 END),
    M_05 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 5 THEN 1 END),
    M_06 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 6 THEN 1 END),
    M_07 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 7 THEN 1 END),
    M_08 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 8 THEN 1 END),
    M_09 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 9 THEN 1 END),
    M_10 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 10 THEN 1 END),
    M_11 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 11 THEN 1 END)
FROM 
    dbo.tblCalendar c
        /* changed "YearNum, MonthNum"  instead of "(YEAR(c.dt), MONTH(c.dt)" */
    CROSS APPLY ( VALUES (DATEFROMPARTS(YearNum, MonthNum, 1)) ) fom (FirstOfMonth)
WHERE 
    /* changed c.MonthNum instead of c.dt */
    c.MonthNum >= MONTH(DATEADD(MONTH, -11, @CurrentMonth))
    /* changed c.MonthNum instead of c.dt */
    AND c.MonthNum < MONTH(DATEADD(MONTH, 1, @CurrentMonth));

对吗?

对不起,我在这里弄糊涂了。这个想法是根本不使用动态sql吗? 只需使用我的查询,即:

;WITH cte_TopClasses
AS  ( 
SELECT
        c.YearNum,
        c.MonthNum,
        DD.ClassCode,
        ISNULL(SUM(prm.Premium),0) as NetWrittenPremium
FROM    tblCalendar c
LEFT JOIN  ProductionReportMetrics prm ON c.YearNum = YEAR(prm.EffectiveDate) and c.MonthNum = MONTH(prm.EffectiveDate) 
           AND CompanyGUID = '18E04C99-D796-4CFA-B1E7-28328321C8AD'      
LEFT JOIN [dbo].[Dynamic_Data_GLUnitedSpecialty] DD on prm.QuoteGUID = DD.QuoteGuid 
WHERE   ( c.YearNum = YEAR(GETDATE())-1 and c.MonthNum >= MONTH(GETDATE())+1 ) OR 
        ( c.YearNum = YEAR(GETDATE()) and c.MonthNum <= MONTH(GETDATE()) ) 
GROUP BY    c.YearNum,
            c.MonthNum,
            DD.ClassCode        
    ) 

select * from cte_TopClasses

输出:

【问题讨论】:

    标签: sql-server visual-studio reporting-services


    【解决方案1】:

    我相信数据源中的表名在保存模式时需要是静态的。话虽如此,您可以根据当前月份的函数命名 SSRS 中的列。因此,您可以让数据集始终将列返回为 11 到 0,并让 SSRS 动态地将 tablix 列命名为当前月份减去列名。

    【讨论】:

    • 谢谢安德鲁,我做到了,但仍然感到困惑。我更新了问题。
    【解决方案2】:

    SSRS 需要一组固定的输入列,这使得动态透视查询完全不兼容。将数据以非透视方式导入 SSRS,并让 SSRS 在矩阵上进行透视。

    编辑...使用非动态 sql...

    按照这些思路做一些事情...

    DECLARE @CurrentMonth DATE = DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()), '19000101');
    
    SELECT 
        M_00 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 0 THEN 1 END),
        M_01 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 1 THEN 1 END),
        M_02 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 2 THEN 1 END),
        M_03 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 3 THEN 1 END),
        M_04 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 4 THEN 1 END),
        M_05 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 5 THEN 1 END),
        M_06 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 6 THEN 1 END),
        M_07 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 7 THEN 1 END),
        M_08 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 8 THEN 1 END),
        M_09 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 9 THEN 1 END),
        M_10 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 10 THEN 1 END),
        M_11 = COUNT(CASE WHEN DATEDIFF(MONTH, fom.FirstOfMonth, @CurrentMonth) = 11 THEN 1 END)
    FROM 
        dbo.Calendar c
        CROSS APPLY ( VALUES (DATEFROMPARTS(YEAR(c.dt), MONTH(c.dt), 1)) ) fom (FirstOfMonth)
    WHERE 
        c.dt >= DATEADD(MONTH, -11, @CurrentMonth)
        AND c.dt < DATEADD(MONTH, 1, @CurrentMonth);
    

    查询输出...

    M_00        M_01        M_02        M_03        M_04        M_05        M_06        M_07        M_08        M_09        M_10        M_11
    ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
    30          31          31          30          31          30          31          28          31          31          30          31
    

    这个想法是,列中的数据随着月份的进展而循环列,但列名始终保持不变......因此它总是与 SSRS 配合得很好。

    然后,返回 SSRS,而不是显示来自查询的标题,而是使用公式表达式。像

    =MonthName(month(Now()))
    =MonthName(month(Now()) + 1)
    =MonthName(month(Now()) + 2)
    =MonthName(month(Now()) + 3)
    ...
    

    【讨论】:

    • 我这样做的全部原因是:stackoverflow.com/questions/46064690/…
    • @Oleg - 你根本不需要动态 sql。我会在几分钟内用更好的解释更新我的答案...
    • @Oleg - 您使用的是什么版本的 SQL Server?
    • 我正在使用 SQL 2012 和 Visual Studio 2010。谢谢
    • 如果您需要更多信息,请告诉我
    猜你喜欢
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多