计算Oracle中的移动平均值并显示期间

时间:2013-04-18 14:03:45

标签: sql oracle

我正在尝试计算Oracle SQL中的10期移动平均值,但似乎无法正确使用它。

我的查询如下:

SELECT
          BSM_ID
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-10/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD1"
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-9/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD2"
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-8/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD3"
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-7/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD4"           
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-6/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD5"           
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-5/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD6"            
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-4/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD7"            
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-3/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD8"    
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-2/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD9"            
          ,CASE
                WHEN D_DTM = (SELECT MAX(D_DTM)-1/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END AS "PERIOD10"            
          ,AVG(
                CASE
                WHEN D_DTM BETWEEN (SELECT MAX(D_DTM)-1/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) AND (SELECT MAX(D_DTM)-10/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                END
              ) AS "10 PERIOD AVG" 

    FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI
    where D_DTM >= (SELECT MAX(D_DTM)-10/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 

    GROUP BY
          BSM_ID
    order by BSM_ID desc

但是继续得到“不是单组组功能”错误。我要做的是按列显示10个周期中的每个周期的%,然后将第11列作为AVG。我记得在SQL中做了类似的事情,但我无法在PLSQL

中找到合成器

在SQL Server中我能够做到这一点来实现相同的结果:

  SELECT         carrier,
             dIVISION,
             LOcATION,
             servicetype
             ,max(@maxwk-1) as ops_week_id
             ,max(case when ops_week_id = @maxwk-2 then (OT * 100.00) / ts else null end)
               as [%_wk_1 ] 
             ,max(case when ops_week_id = @maxwk-3 then (OT * 100.00) / ts else null end)
               as [%_wk_2 ]   
             ,max(case when ops_week_id = @maxwk-4 then (OT * 100.00) / ts else null end)
               as [%_wk_3 ]
             ,max(case when ops_week_id = @maxwk-5 then (OT * 100.00) / ts else null end)
               as [%_wk_4 ]
             ,avg(case when ops_week_id Between @maxwk-5 and @maxwk - 2  then (OT * 100.00) / ts else null end)
               as [4_wk_SMA]
             ,avg(case when ops_week_id Between @maxwk-5 and @maxwk - 2  then (OT * 100.00) / ts else null end)
               - 0.15 as [LwrBand]            
             ,avg(case when ops_week_id Between @maxwk-5 and @maxwk - 2  then (OT * 100.00) / ts else null end)
               + 0.15 as [UprBand]  
             ,max(case when ops_week_id = @maxwk-1 then (OT * 100.00) / ts else null end)
               as [Ops_wk_id_av] 
         FROM la

       GROUP BY la.DIVISION,la.LOCATION,la.servicetype,la.carrier

原始表结构如下:

     D_DTM (datetime)
     F_ID
     REG_DTM
     MRKT_ID
     MRKT_NM
     CL_ID
     CL_NM
     BSM_ID
     BSM_NM
     BSC_SEQ_ID
     CSCD_ID
     CSCD_NM
     BTS_ID
     V_ATT_CNT (denominator)
     V_MBL_ORG_CNT
     V_MBL_TER_CNT
     V_SILENT_RETRY_CNT
     V_CUST_BLK_CNT (numerator)

我想要做的是在最近10个小时内取百分比(V_CUST_BLK_CNT / V_ATT_CNT),然后按BSM_ID平均。因此生成的查询具有这样的结构

BSM_ID | PERIOD1%| PERIOD2%| PERIOD3%|等... | AVG%

我觉得我应该能够使用case whens来做到这一点,但似乎无法让小组和语法工作......

2 个答案:

答案 0 :(得分:0)

您收到错误是因为您按bsm_id进行分组,但引用了许多其他没有聚合函数的列。

如果您使用的是Oracle,请使用内置函数进行移动平均。这些是具有range关键字的分析函数,类似于:

select bsm.*,
       (sum(V_CUST_BLK_CNT) over (partition by bsm_id order by d_dtm range between 10 preceding and current row) /
       (sum(V_CUST_ATT_CNT) over (partition by bsm_id order by d_dtm range between 10 preceding and current row))
from bsm

答案 1 :(得分:0)

好的,所以我的查询工作方式如下:

SELECT 
    BSM_ID
    ,MAX(PERIOD1) AS "PERIOD1"
    ,MAX(PERIOD2) AS "PERIOD2"
    ,MAX(PERIOD3) AS "PERIOD3"
    ,MAX(PERIOD4) AS "PERIOD4"
    ,MAX(PERIOD5) AS "PERIOD5"
    ,MAX(PERIOD6) AS "PERIOD6"
    ,MAX(PERIOD7) AS "PERIOD7"
    ,MAX(PERIOD8) AS "PERIOD8"
    ,MAX(PERIOD9) AS "PERIOD9"
    ,MAX(PERIOD10) AS "PERIOD10"
    ,(MAX(PERIOD1)+MAX(PERIOD2)+MAX(PERIOD3)+MAX(PERIOD4)+MAX(PERIOD5)+MAX(PERIOD6)+MAX(PERIOD7)+MAX(PERIOD8)+MAX(PERIOD9)+MAX(PERIOD10))/10 AS "AVG"

    FROM
           (

            SELECT
                  BSM_ID
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-10/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                        END AS "PERIOD1"
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-9/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                        END AS "PERIOD2"
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-8/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END)
                        END AS "PERIOD3"
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-7/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END)
                        END AS "PERIOD4"           
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-6/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END)
                        END AS "PERIOD5"           
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-5/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                        END AS "PERIOD6"            
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-4/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                        END AS "PERIOD7"            
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-3/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                        END AS "PERIOD8"    
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-2/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                        END AS "PERIOD9"            
                  ,CASE
                        WHEN D_DTM = (SELECT MAX(D_DTM)-1/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI) 
                        THEN (CASE WHEN sum(V_ATT_CNT) = 0 THEN NULL ELSE sum(V_CUST_BLK_CNT)/sum(V_ATT_CNT) END) 
                        END AS "PERIOD10"            


            FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI

            WHERE D_DTM >=(SELECT MAX(D_DTM)-10/24 FROM DMSN.DS3R_FH_1XRTT_BTS_LVL_KPI)

            GROUP BY BSM_ID, D_DTM

            )
    GROUP BY
    BSM_ID

我确信有一种更有效的方法可以做到这一点,但这很有效。