多个联盟声明中的分区和排序

时间:2017-07-24 16:16:31

标签: sql-server tsql group-by ssms union-all

早上好,

我正在努力将我们的仪表板团队的许多指标组合成一个可复制到Excel中的单个可执行存储过程,然后让数据透视表做一些魔术。话虽如此,为了这个问题,我只会引用一个较小的数据集来表示单个指标,以保持简单。 他们想要标题和标签的方式是非常具体的,这就是为什么前几组以他们的方式编写的原因。如果需要,我可以提供更多信息。

以下是我想知道是否有人可以帮助我的问题:

  1. 他们想要查询中的放电月份名称。这很好,但是一旦我将放电日期(projected_d)添加到查询中,我还必须使用group by。然后,这会导致任何没有数据的MonthMeasure从结果集中完全消失。我想为该线显示零而不是消失。如果我从查询中删除了monthgroup by,则会显示零。

  2. 由于ORDER BY,我无法对Months使用Union All语句。 我想在结果集中显示月份名称,但按MONTH编号排序。在正常查询中,我通常不会遇到问题,但由于此查询中的Union All,我遇到了在何处或如何使其发挥作用的问题。

  3. 这是当前查询和结果集:

    USE COMPANY_VHR_PROD
    GO
    
    DECLARE @MINDOS DATE,
            @MAXDOS DATE,
            @PRTFSuccess INT,
            @PRTFTotal INT
    
    SET @MINDOS = '20170701'
    SET @MAXDOS = '20170803'
    
    SELECT @PRTFSuccess = COUNT(DISTINCT uniqueid_c)
    FROM cd.enrollments
    WHERE
        program_c = 'PRTF'
        AND level_c IN ('SIG', 'MOD')
        AND projected_d BETWEEN @MINDOS AND @MAXDOS
    
    SELECT @PRTFTotal = COUNT(DISTINCT uniqueid_c)
    FROM cd.enrollments
    WHERE
        program_c = 'PRTF'
        AND projected_d BETWEEN @MINDOS AND @MAXDOS
    
    SELECT
        '' AS "Program",
        '' AS "Measurement",
        '' AS "Month",
        '' AS "Count or Total",
        '' AS "Percentage or Average",
        '' AS "YTD"
    WHERE 1=0
    
    UNION ALL
    
    SELECT
        '',
        '',
        '',
        '',
        '',
        ''
    
    UNION ALL
    
    SELECT
        'PRTF',
        'Client Response To Treatment',
        'Month',
        'Count',
        'Percentage',
        'YTD'
    
    UNION ALL
    
    SELECT
        'PRTF' AS "Program",
        CASE 
            WHEN e.level_c IS NULL THEN 'None Entered' 
            WHEN e.level_c = '' THEN 'None Entered' 
            WHEN e.level_c = 'SIG' THEN 'Significant Success Experienced'
            WHEN e.level_c = 'MOD' THEN 'Moderate Success Experienced'
            WHEN e.level_c = 'MILD' THEN 'Mild Success Experienced'
            WHEN e.level_c = 'INS' THEN 'Insignificant Success Experienced' 
            ELSE e.level_c END AS "Success",
        DATENAME(MONTH,e.projected_d),
        CONVERT(VARCHAR,COUNT(DISTINCT e.uniqueid_c),1) AS "Count",
        CONVERT(VARCHAR,CAST((COUNT(DISTINCT e.uniqueid_c) / CONVERT(DECIMAL(10,2),@PRTFTotal))*100 AS DECIMAL(10,2)),1),
        CONVERT(VARCHAR,SUM(COUNT(DISTINCT e.uniqueid_c)) OVER (PARTITION BY e.level_c),1)
    FROM cd.enrollments e
    WHERE
        e.program_c = 'PRTF'
        AND e.projected_d BETWEEN @MINDOS and @MAXDOS
    GROUP BY e.level_c, DATENAME(MONTH,e.projected_d)
    
    UNION ALL
    
    SELECT
        'PRTF' AS "Program",
        'Total Clients Discharging' AS "Client Response to Treatment",
        'All',
        CONVERT(VARCHAR,COUNT(DISTINCT e.uniqueid_c),1) AS "Count",
        CONVERT(VARCHAR,CAST((COUNT(DISTINCT e.uniqueid_c) / CONVERT(DECIMAL(10,2),@PRTFTotal))*100 AS DECIMAL(10,2)),1),
        CONVERT(VARCHAR,COUNT(DISTINCT e.uniqueid_c),1) AS "YTD"
    FROM cd.enrollments e
    WHERE
        e.program_c = 'PRTF'
        AND e.projected_d BETWEEN @MINDOS and @MAXDOS
    

    ResultSet

    理想情况下,我希望它按此顺序显示这样的内容:

    PRTF - Insignificant Success - July   - 0 -   0.00 - 0
    PRTF - Insignificant Success - August - 0 -   0.00 - 0
    PRTF - Mild Success          - July   - 0 -   0.00 - 0
    PRTF - Mild Success          - August - 0 -   0.00 - 0
    PRTF - Moderate Success      - July   - 1 -  25.00 - 1
    PRTF - Moderate Success      - August - 0 -   0.00 - 1
    PRTF - Significant Success   - July   - 2 -  50.00 - 3
    PRTF - Significant Success   - August - 1 -  25.00 - 3
    PRTF - Total Clients         - All    - 4 - 100.00 - 4
    

    任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

您可以使用子查询注入月份编号和排序顺序来处理标题,正文和页脚的排序。子查询仍将与UNION ALL组合,但它允许您只选择结果集的相关列,同时为排序提供使用元数据。

-- Load headers with sub-query to hide sort order attribute
SELECT
    [Program],[Measurement],[Month],[Count or Total],[Percentage or Average],[YTD]
FROM (
    SELECT '', '', '', '', '', '', 10, 0 -- SortOrder, MonthOrder
    UNION ALL SELECT 'PRTF', 'Client Response To Treatment', 'Month', 'Count', 'Percentage', 'YTD', 20, 0 -- SortOrder, MonthOrder
) Headers ([Program],[Measurement],[Month],[Count or Total],[Percentage or Average],[YTD], SortOrder, MonthOrder)

UNION ALL

-- Load records with sub-query to hide sort order attribute
SELECT
    [Program],[Measurement],[Month],[Count or Total],[Percentage or Average],[YTD]
FROM (
    SELECT
        'PRTF' AS "Program",
        CASE 
            WHEN e.level_c IS NULL THEN 'None Entered' 
            WHEN e.level_c = '' THEN 'None Entered' 
            WHEN e.level_c = 'SIG' THEN 'Significant Success Experienced'
            WHEN e.level_c = 'MOD' THEN 'Moderate Success Experienced'
            WHEN e.level_c = 'MILD' THEN 'Mild Success Experienced'
            WHEN e.level_c = 'INS' THEN 'Insignificant Success Experienced' 
            ELSE e.level_c END AS "Success",
        DATENAME(MONTH,e.projected_d),
        CONVERT(VARCHAR,COUNT(DISTINCT e.uniqueid_c),1) AS "Count",
        CONVERT(VARCHAR,CAST((COUNT(DISTINCT e.uniqueid_c) / CONVERT(DECIMAL(10,2),@PRTFTotal))*100 AS DECIMAL(10,2)),1),
        CONVERT(VARCHAR,SUM(COUNT(DISTINCT e.uniqueid_c)) OVER (PARTITION BY e.level_c),1),
        30, DATEPART(MONTH,e.projected_d) -- Add SortOrder, MonthOrder
    FROM cd.enrollments e
    WHERE
        e.program_c = 'PRTF'
        AND e.projected_d BETWEEN @MINDOS and @MAXDOS
    GROUP BY e.level_c, DATENAME(MONTH,e.projected_d)
    ) Records ([Program],[Measurement],[Month],[Count or Total],[Percentage or Average],[YTD], SortOrder, MonthOrder)

UNION ALL

-- Load footer with sub-query to hide sort order attribute
SELECT
    [Program],[Measurement],[Month],[Count or Total],[Percentage or Average],[YTD]
FROM (
    SELECT
        'PRTF' AS "Program",
        'Total Clients Discharging' AS "Client Response to Treatment",
        'All',
        CONVERT(VARCHAR,COUNT(DISTINCT e.uniqueid_c),1) AS "Count",
        CONVERT(VARCHAR,CAST((COUNT(DISTINCT e.uniqueid_c) / CONVERT(DECIMAL(10,2),@PRTFTotal))*100 AS DECIMAL(10,2)),1),
        CONVERT(VARCHAR,COUNT(DISTINCT e.uniqueid_c),1) AS "YTD",
        40, 0 -- Add SortOrder and month order
    FROM cd.enrollments e
    WHERE
        e.program_c = 'PRTF'
        AND e.projected_d BETWEEN @MINDOS and @MAXDOS
    ) Footers ([Program],[Measurement],[Month],[Count or Total],[Percentage or Average],[YTD], SortOrder, MonthOrder)

ORDER BY
    SortOrder, [Program], [Measurement], [MonthOrder]