0

我正在尝试在 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 | 期间1% | 期间2% | 期间3% | 等等... | 平均百分比

我觉得我应该能够使用 case whens 来执行此操作,但似乎无法让 group by 和语法工作......

4

2 回答 2

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
于 2013-04-18T14:14:21.160 回答
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

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

于 2013-04-18T17:57:13.793 回答