如何在SSRS报告构建器中按一系列日期进行分组?

时间:2018-04-30 18:08:13

标签: reporting-services grouping date-range

我有一份健康计划的个人订阅者列表。每个订户都有一系列日期,以表明该计划的资格。为了帮助说明,这里是2018年至Q1期间符合条件的订阅者的模拟记录列表,用MS-Server的T-SQL编写:

-- qryEligibleSubscribers2018-Q1Simple

WITH
    S
AS
(
-- MOCK LIST OF SUBSCRIBERS TO HEALTH PLAN
-- WITH ELIGIBILITY TIME FRAMES
    SELECT
-- CONTINUOUSLY ELIGIBLE SINCE 2017
        '0001' AS ID,
        'MOUSE' AS LASTNAME,
        'MICKEY' AS FIRSTNAME,
        '1/1/2017' AS EFFECTIVE,
        NULL AS TERM
    UNION ALL SELECT
-- CURRENT SUBSCRIBER SINCE FEB. 2018
        '0002' AS ID,
        'MOUSE' AS LASTNAME,
        'MINNIE' AS FIRSTNAME,
        '2/1/2018' AS EFFECTIVE,
        NULL AS TERM
    UNION ALL SELECT
-- SUBSCRIBED TO PLAN FOR JAN. 2018 ONLY
        '0003' AS ID,
        'DUCK' AS LASTNAME,
        'DONALD' AS FIRSTNAME,
        '1/1/2018' AS EFFECTIVE,
        '1/31/2018' AS TERM
    UNION ALL SELECT
-- SUBSCRIBED TO PLAN STARTING IN 2018-Q2
        '0004' AS ID,
        'GOOF' AS LASTNAME,
        'GOOFY' AS FIRSTNAME,
        '4/1/2018' AS EFFECTIVE,
        NULL AS TERM
)
-- LIST OF SUBSCRIBERS
-- WHO WERE ELIGIBLE IN 2018-Q1 ONLY
SELECT
    S.ID,
    S.LASTNAME,
    S.FIRSTNAME,
    S.EFFECTIVE,
    S.TERM
FROM
    S
WHERE
-- LIMIT LIST TO 2018-Q1
    S.EFFECTIVE <= '3/31/2018'
AND
    ISNULL(S.TERM,GETDATE()) >= '1/1/2018'

结果,运行时,这三个(四个)订阅者:

ID      LASTNAME    FIRSTNAME   EFFECTIVE   TERM
-----------------------------------------------------
0001    MOUSE       MICKEY      1/1/2017
0002    MOUSE       MINNIE      2/1/2018
0003    DUCK        DONALD      1/1/2018    1/31/2018
-----------------------------------------------------

从结果可以看出,米老鼠在2018年至第一季度的所有三个月都有资格,明妮老鼠有资格参加2月份的比赛。仅限3月份,唐老鸭才有资格参加本季度的第一个月,而高飞则在2018年至第二季度进入该计划,因此不包括在结果集中。

我需要报告每个月的总用户数。我可以使用这个更复杂的查询来完成此操作,该查询也是用MS-SQL Server的T-SQL编写的:

-- qryEligibleSubscribers2018-Q1Complex

WITH
-- LIST OF MONTHS IN 2018-Q1
    R(BOR,EOR)
AS
(
-- FIXED RANGE OF MONTHS IN 2018-Q1
    SELECT
        DATEADD(M,DATEDIFF(M,0,'1/1/2018'),0) AS BOR,
        DATEADD(M,DATEDIFF(M,0,'3/31/2018'),0) AS EOR
-- RECURSIVELY ADD A MONTH
    UNION ALL SELECT
        DATEADD(M,1,R.BOR) AS BOR,
        R.EOR
    FROM
        R
    WHERE
        R.BOR < R.EOR
),
    S
AS
(
-- MOCK LIST OF SUBSCRIBERS TO HEALTH PLAN
-- WITH ELIGIBILITY TIME FRAMES
    SELECT
-- CONTINUOUSLY ELIGIBLE SINCE 2017
        '0001' AS ID,
        'MOUSE' AS LASTNAME,
        'MICKEY' AS FIRSTNAME,
        '1/1/2017' AS EFFECTIVE,
        NULL AS TERM
    UNION ALL SELECT
-- CURRENT SUBSCRIBER SINCE FEB. 2018
        '0002' AS ID,
        'MOUSE' AS LASTNAME,
        'MINNIE' AS FIRSTNAME,
        '2/1/2018' AS EFFECTIVE,
        NULL AS TERM
    UNION ALL SELECT
-- SUBSCRIBED TO PLAN FOR JAN. 2018 ONLY
        '0003' AS ID,
        'DUCK' AS LASTNAME,
        'DONALD' AS FIRSTNAME,
        '1/1/2018' AS EFFECTIVE,
        '1/31/2018' AS TERM
    UNION ALL SELECT
-- SUBSCRIBED TO PLAN STARTING IN 2018-Q2
        '0004' AS ID,
        'GOOF' AS LASTNAME,
        'GOOFY' AS FIRSTNAME,
        '4/1/2018' AS EFFECTIVE,
        NULL AS TERM
),
    X
AS
(
-- EXTENDED LIST OF SUBSCRIBERS
-- WHO WERE ELIGIBLE IN 2018-Q1 ONLY
-- LISTING EACH MONTH OF ELIGIBILITY
    SELECT
        R.BOR AS MONTH,
        FORMAT(R.BOR,'MMMM yyyy') AS LABEL,
        S.ID,
        S.LASTNAME,
        S.FIRSTNAME,
        S.EFFECTIVE,
        S.TERM
    FROM
        S
    INNER JOIN
        R
    ON
        S.EFFECTIVE < DATEADD(M,1,R.BOR)
    AND
        ISNULL(S.TERM,GETDATE()) >= R.BOR
)
SELECT
    X.LABEL AS MONTH,
    COUNT(X.ID) AS TOTAL
FROM
    X
GROUP BY
    X.LABEL,
    X.MONTH
ORDER BY
    X.MONTH

结果显示,第一季度共有两名订阅者符合资格:

MONTH       TOTAL
-----------------
January 2018    2
February 2018   2
March 2018      2
-----------------

要查看详细/未聚合的结果 - 具体而言,哪个订阅者在几个月内符合条件,我们可以运行此查询(也使用T-SQL编写的MS-SQL Server):

-- qryEligibleSubscribers2018-Q1Detailed

WITH
-- LIST OF MONTHS IN 2018-Q1
    R(BOR,EOR)
AS
(
-- FIXED RANGE OF MONTHS IN 2018-Q1
    SELECT
        DATEADD(M,DATEDIFF(M,0,'1/1/2018'),0) AS BOR,
        DATEADD(M,DATEDIFF(M,0,'3/31/2018'),0) AS EOR
-- RECURSIVELY ADD A MONTH
    UNION ALL SELECT
        DATEADD(M,1,R.BOR) AS BOR,
        R.EOR
    FROM
        R
    WHERE
        R.BOR < R.EOR
),
    S
AS
(
-- MOCK LIST OF SUBSCRIBERS TO HEALTH PLAN
-- WITH ELIGIBILITY TIME FRAMES
    SELECT
-- CONTINUOUSLY ELIGIBLE SINCE 2017
        '0001' AS ID,
        'MOUSE' AS LASTNAME,
        'MICKEY' AS FIRSTNAME,
        '1/1/2017' AS EFFECTIVE,
        NULL AS TERM
    UNION ALL SELECT
-- CURRENT SUBSCRIBER SINCE FEB. 2018
        '0002' AS ID,
        'MOUSE' AS LASTNAME,
        'MINNIE' AS FIRSTNAME,
        '2/1/2018' AS EFFECTIVE,
        NULL AS TERM
    UNION ALL SELECT
-- SUBSCRIBED TO PLAN FOR JAN. 2018 ONLY
        '0003' AS ID,
        'DUCK' AS LASTNAME,
        'DONALD' AS FIRSTNAME,
        '1/1/2018' AS EFFECTIVE,
        '1/31/2018' AS TERM
    UNION ALL SELECT
-- SUBSCRIBED TO PLAN STARTING IN 2018-Q2
        '0004' AS ID,
        'GOOF' AS LASTNAME,
        'GOOFY' AS FIRSTNAME,
        '4/1/2018' AS EFFECTIVE,
        NULL AS TERM
)
-- EXTENDED LIST OF SUBSCRIBERS
-- WHO WERE ELIGIBLE IN 2018-Q1 ONLY
-- LISTING EACH MONTH OF ELIGIBILITY
SELECT
    FORMAT(R.BOR,'MMMM yyyy') AS LABEL,
    S.ID,
    S.LASTNAME,
    S.FIRSTNAME,
    S.EFFECTIVE,
    S.TERM
FROM
    S
INNER JOIN
    R
ON
    S.EFFECTIVE < DATEADD(M,1,R.BOR)
AND
    ISNULL(S.TERM,GETDATE()) >= R.BOR
ORDER BY
    R.BOR,
    S.ID

详细的逐月结果是:

MONTH           ID      LASTNAME    FIRSTNAME   EFFECTIVE   TERM
---------------------------------------------------------------------
January 2018    0001    MOUSE       MICKEY      1/1/2017
January 2018    0003    DUCK        DONALD      1/1/2018    1/31/2018
February 2018   0001    MOUSE       MICKEY      1/1/2017
February 2018   0002    MOUSE       MINNIE      2/1/2018
March 2018      0001    MOUSE       MICKEY      1/1/2017
March 2018      0002    MOUSE       MINNIE      2/1/2018
---------------------------------------------------------------------

使用原始的简单查询,结果集会提供三条记录,每个记录在整个感兴趣的日期范围内(2018-Q1)。

ID      LASTNAME    FIRSTNAME   EFFECTIVE   TERM
-----------------------------------------------------
0001    MOUSE       MICKEY      1/1/2017
0002    MOUSE       MINNIE      2/1/2018
0003    DUCK        DONALD      1/1/2018    1/31/2018
-----------------------------------------------------

通过更复杂,详细的查询,结果集提供了六条记录,每个月一个记录,其中订阅者有资格获得感兴趣的季度中的特定月份。

MONTH           ID      LASTNAME    FIRSTNAME   EFFECTIVE   TERM
---------------------------------------------------------------------
January 2018    0001    MOUSE       MICKEY      1/1/2017
January 2018    0003    DUCK        DONALD      1/1/2018    1/31/2018
February 2018   0001    MOUSE       MICKEY      1/1/2017
February 2018   0002    MOUSE       MINNIE      2/1/2018
March 2018      0001    MOUSE       MICKEY      1/1/2017
March 2018      0002    MOUSE       MINNIE      2/1/2018
---------------------------------------------------------------------

在实践中,我们有数十万订阅者。使用更复杂的查询会提供难以处理的结果集(例如,在12个月的时间内,成千上万条记录中的每条记录最多可以多达12次......每个月一次。)我需要保留我的简单查询作为驱动我的SSRS报告的引擎。使用简单的结果集......:

ID      LASTNAME    FIRSTNAME   EFFECTIVE   TERM
-----------------------------------------------------
0001    MOUSE       MICKEY      1/1/2017
0002    MOUSE       MINNIE      2/1/2018
0003    DUCK        DONALD      1/1/2018    1/31/2018
-----------------------------------------------------

...我似乎无法弄清楚如何在SSRS中构建一个能够按月提供订阅总数的报告。换句话说,我希望并且需要SSRS Reporting Services来将记录乘以/拆分/复制到相应的合格月份,而不是基础SQL查询:

MONTH       TOTAL
-----------------
January 2018    2
February 2018   2
March 2018      2
-----------------

问题的实质是尽可能地弄清楚如何在SSRS中分割和分组日期范围,就像我在更复杂的SQL查询中所做的那样。

我已尝试在报表生成器中使用各种风格的Lookup(),但这些需要一对一匹配,例如,MultiLookup()从数据集中检索名称 - 值对的一组值,其中每个对有一对一的关系。

在我的示例中,该季度中的特定月份必须与订户集中的特定月份(在几个月的范围内)匹配。在这里,正如我们在简单查询中看到的那样,订阅者可以在几个月的范围内获得资格。我相信如果存在Lookup()的某些变体,我可以在报表生成器中成功构建SSRS报表,该变量会打开另一个数据集中的一系列键中是否存在一个数据集中的特定键(例如,2018年1月)(2016年8月) - 2018年5月),而不是精确的一对一比赛。

结果的格式并不重要。可以是图表或Tablix。如果可能的话,现在只想获得结果。

1 个答案:

答案 0 :(得分:0)

否 - 遗憾的是,我想不出一个简单的方法可以让SSRS按月分组,并根据需要计算每个SSRS。

如果您只是想避免运行多个查询,可能适用于您的情况的是使用临时表

您的第一个数据集会将详细数据放在临时表中,并从表中选择详细信息。

第二个数据集将使用第一个数据集中的详细信息临时表来汇总您的每月总计。对于使用在先前数据集中创建的临时表的数据集,您需要在字段选项卡中手动输入字段名称。

检查数据源属性中的使用单一交易框,以便保留临时表。