【问题标题】:How to calculate cumulative 90th percentile by period in ORACLE SQL如何在 ORACLE SQL 中按周期计算累计第 90 个百分位数
【发布时间】:2018-11-25 12:32:39
【问题描述】:

任务:我想计算第 90 个百分位等待时间的累积值(以天为单位),以确定患者在每个时期和财政年度(包括所有设施的总数)按设施等待超声扫描的时间。

如何:我使用 over(partition by) 表达式来获取 Oracle SQL 中累积的第 90 个百分位数据。

ISSUE: 收到错误 (ORA-00979) “wait_time_days 不是 GROUP BY 表达式”指出累积第 90 个百分位数的表达式 -

这是查询的简化版本:

    define period_start = to_date ('20170401', 'yyyy-mm-dd')
    define period_end = to_date ('20180331', 'yyyy-mm-dd')   

            Select 
            to_char(add_months(c.PROCEDURE_PERFORMED_DT, -3),'YYYY') ||'/'|| to_char(add_months(c.PROCEDURE_PERFORMED_DT, 9),'YY') as Fiscal_year

            , nvl (CASE WHEN c.FACILITY_ID = 1 then 'OKANAGAN CLINIC'
                    WHEN c.FACILITY_ID = 2 THEN 'MELBOURNE CLINIC'
                    WHEN c.FACILITY_ID = 3 THEN 'VANCOUVER CLINIC'
                    WHEN c.FACILITY_ID = 4 THEN 'SHWARZ CLINIC'
                    WHEN c.FACILITY_ID = 5 THEN 'LADYSMITH CLINIC'
                    END, 'TOTAL') as FACILITY,
            , c.PROCEDURE_PERFORMED_DT
            , c.BOOKING_DT
            , round((c.PROCEDURE_PERFORMED_DT - c.BOOKING_FORM_RECEIVED_DT),2) as wait_time
            , p.period

        , round(percentile_cont(0.9) within group (order by wait_time asc),2) as Percentile_90th

        , percentile_cont(0.9) within group (order by wait_time asc)
     over(partition by CASE WHEN c.FACILITY_ID = 1 then 'OKANAGAN CLINIC'
                    WHEN c.FACILITY_ID = 2 THEN 'MELBOURNE CLINIC'
                    WHEN c.FACILITY_ID = 3 THEN 'VANCOUVER CLINIC'
                    WHEN c.FACILITY_ID = 4 THEN 'SHWARZ CLINIC'
                    WHEN c.FACILITY_ID = 5 THEN 'LADYSMITH CLINIC'
                    END) as Cumulative_Perc90th

    FROM COMPLETED_PROCEDURE c, PERIOD p   

     WHERE c.PROCEDURE_PERFORMED_DT between &period_start and &period_end
                   and c.PROCEDURE_PERFORMED_DT = p.END_DATE

                Group by 
                Fiscal_year
                , Rollup(CASE WHEN c.FACILITY_ID = 1 then 'OKANAGAN CLINIC'
                    WHEN c.FACILITY_ID = 2 THEN 'MELBOURNE CLINIC'
                    WHEN c.FACILITY_ID = 3 THEN 'VANCOUVER CLINIC'
                    WHEN c.FACILITY_ID = 4 THEN 'SHWARZ CLINIC'
                    WHEN c.FACILITY_ID = 5 THEN 'LADYSMITH CLINIC'
                    END)
                , period

Order By Facility, period
;

PERIOD 表 (p) 包含一些期间日期的列表,如下所示:

PERIOD   START_DATE     END_DATE

    01  2017-04-01  2017-04-20

    02  2017-04-21  2017-05-18

    03  2017-05-19  2017-06-15

    04  2017-06-16  2017-07-13

感谢您的帮助!

附:我正在使用相同的方法来计算累积量(通过对所有计数的扫描求和)并且它可以正常工作。

【问题讨论】:

  • 你有几个带有额外逗号的列表达式;您似乎在rollup() 中非法使用了facility 别名(相同级别的查询,如图所示);而您没有在您的 group-by 子句中有 wait_time_days 那么这应该是在演示第一个或第二个错误吗?目前还不清楚,简化代码似乎引起了令人分心的问题。 See MCVE.
  • 只是我的两分钱——我想你想使用一些内嵌视图。您在 sql 中使用别名(如 wait_time_days)——但这些别名不能在其他列中引用,除非您将其全部包装在内联视图中(或创建视图)并在外部 sql
  • @AlexPoole:感谢您的评论。我已经编辑了代码并删除了多余的逗号。此外,我在汇总中使用了 Facility 的整个 CASE 语句。我想集中精力解决关于在我的 group-by 子句中有 wait_time 的第一个错误。我将不胜感激。

标签: oracle percentile


【解决方案1】:

我不太确定你想从这个查询中得到什么结果,但通常会出现错误 ORA-00979,因为你正在尝试使用包含 OVER(...) 子句的 PERCENTILE_CONT 的分析版本在聚合的 GROUP BY 查询中。


我尝试使用简化的example 来说明这个问题,我希望这能帮助你理解错误是什么以及应该如何使用这个函数。

假设我们有下表和 3诊所和每个诊所 10 条记录:

CREATE TABLE example(
  clinic varchar2(100),
  wait_days_period int
);

INSERT ALL
INTO example VALUES('MELBOURNE CLINIC', x )
INTO example VALUES('VANCOUVER CLINIC', 10 + x )
INTO example VALUES('SHWARZ CLINIC', 10 * x )
SELECT level as X FROM dual
CONNECT BY LEVEL <= 10;

查询的聚合版本如下所示 - 它包含 GROUP BY 查询中使用的 PERCENTILE_CONT 函数没有 OVER 子句

SELECT clinic,
       PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY wait_days_period) as percen
FROM example
GROUP BY clinic;

|           CLINIC | PERCEN |
|------------------|--------|
| MELBOURNE CLINIC |    9.1 |
|    SHWARZ CLINIC |     91 |
| VANCOUVER CLINIC |   19.1 |

analyticac 版本的查询如下所示 - 它包含在简单(非 GROUP BY)查询中使用的 PERCENTILE_CONT 函数 WITH OVER 子句

SELECT clinic, wait_days_period,
       PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY wait_days_period) 
       OVER (PARTITION BY clinic) as percen
FROM example  ORDER BY 1,2;

|           CLINIC | WAIT_DAYS_PERIOD | PERCEN |
|------------------|------------------|--------|
| MELBOURNE CLINIC |                1 |    9.1 |
| MELBOURNE CLINIC |                2 |    9.1 |
| MELBOURNE CLINIC |                3 |    9.1 |
| MELBOURNE CLINIC |                4 |    9.1 |
| MELBOURNE CLINIC |                5 |    9.1 |
| MELBOURNE CLINIC |                6 |    9.1 |
| MELBOURNE CLINIC |                7 |    9.1 |
| MELBOURNE CLINIC |                8 |    9.1 |
| MELBOURNE CLINIC |                9 |    9.1 |
| MELBOURNE CLINIC |               10 |    9.1 |
|    SHWARZ CLINIC |               10 |     91 |
|    SHWARZ CLINIC |               20 |     91 |
|    SHWARZ CLINIC |               30 |     91 |
|    SHWARZ CLINIC |               40 |     91 |
|    SHWARZ CLINIC |               50 |     91 |
|    SHWARZ CLINIC |               60 |     91 |
|    SHWARZ CLINIC |               70 |     91 |
|    SHWARZ CLINIC |               80 |     91 |
|    SHWARZ CLINIC |               90 |     91 |
|    SHWARZ CLINIC |              100 |     91 |
| VANCOUVER CLINIC |               11 |   19.1 |
| VANCOUVER CLINIC |               12 |   19.1 |
| VANCOUVER CLINIC |               13 |   19.1 |
| VANCOUVER CLINIC |               14 |   19.1 |
| VANCOUVER CLINIC |               15 |   19.1 |
| VANCOUVER CLINIC |               16 |   19.1 |
| VANCOUVER CLINIC |               17 |   19.1 |
| VANCOUVER CLINIC |               18 |   19.1 |
| VANCOUVER CLINIC |               19 |   19.1 |
| VANCOUVER CLINIC |               20 |   19.1 |

简而言之,分析版本计算的值与聚合版本完全相同(在 GROUP BY 查询中),但允许将其用于普通查询中的每条记录,而无需执行额外的 GROUP BY 子查询。


如果您尝试在 GROUP BY 查询中使用函数的解析版本(带有 OVER... 子句),您将得到 ORA-00979: not a GROUP BY expression,因为这是不允许的:

SELECT clinic,
       PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY wait_days_period) 
       OVER (PARTITION BY clinic) as percen
FROM example
GROUP BY clinic;

ORA-00979: not a GROUP BY expression

【讨论】:

    猜你喜欢
    • 2019-04-06
    • 2015-08-01
    • 1970-01-01
    • 2012-11-01
    • 2012-10-28
    • 2021-09-23
    • 2018-11-04
    • 1970-01-01
    • 2011-10-10
    相关资源
    最近更新 更多