如何在ORACLE SQL中按周期计算累积的第90百分位数

时间:2018-06-15 16:14:01

标签: oracle percentile

任务:我想计算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

感谢您的帮助!

P.S。我使用相同的方法来计算累积量(通过对所有计算的扫描进行求和),并且它没有任何问题。

1 个答案:

答案 0 :(得分:0)

我不太确定您希望从此查询中获得什么结果,但通常会出现错误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