【问题标题】:Oracle - From WebFocus to Oracle - Sum with caseOracle - 从 WebFocus 到 Oracle - 用案例求和
【发布时间】:2016-10-17 19:10:08
【问题描述】:

我有一个在 WebFocus 中创建的 ETL,并将其迁移到 Oracle。

我想要以下情况的替代方案。在 WebFocus 中,他可以使用之前计算的列,作为参数来计算另一个值。

例子:

SUM(CASE
   WHEN T1.M2143831 > T1.M2460254
     THEN
       (T1.M2143831 * 100 / T1.M2143833)
     ELSE
       (T1.M2460254 * 100 / T1.M2460256)
END) AS TAXA_L,
SUM(CASE
   WHEN T4.FABR_ID = 'TEST'
        AND TAX_L >= 80
     THEN  1
   ELSE NULL
END) OVER80

例如,它使用上一步计算的TAX_L作为第二个case的参数,Oracle不能这样做。 我尝试如下:

SUM(CASE
      WHEN T4.FABR_ID = 'TEST'
         AND SUM(CASE
                    WHEN T1.M2143831 > T1.M2460254
                    THEN
                        (T1.M2143831 * 100 / T1.M2143833)
                    ELSE
                        (T1.M2460254 * 100 / T1.M2460256)
                 END) >= 80
      THEN
         1
      ELSE
         NULL
END)AS OVER80

但我收到以下错误:

ORA-00937: 不是单组群函数

这种情况的任何替代方案?

--- 原始查询/WebFocus 的一部分

  SELECT   T4.FABR_ID,
           T3.REPORT_DATE_TIME,
           T3.DAY_OF_WEEK,
           T4.REGIONAL_ID,
           T4.UF_ID,
           T4.BSC_ID,
           T2.COD_IBGE,
           T4.BTS_ID,
           SUM (T1.M2251827) AS CAP_ALLOC,
           SUM(CASE
                  WHEN T1.M2143831 > T1.M2460254
                  THEN
                     (T1.M2143831 * 100 / T1.M2143833)
                  ELSE
                     (T1.M2460254 * 100 / T1.M2460256)
               END)
              AS TAX_L,
           SUM (100 * T1.M2489212 / T1.M2489213) AS IUB_FRAME_LOST,
           SUM (T1.M1979632 * T1.M1979630) AS NUM_ACE,
           SUM (T1.M1977785 * T1.M1973189) AS DEN_ACE,
           SUM (T1.M2225994) AS THROUGHPUT_IUB_DOWNLINK_E,
           SUM(  (T1.M2016166 + T1.M2016172 + T1.M1978319 + T1.M1978331)
               * 8
               / 3600)
              AS THROUGHPUT_DADOS_TOTAL_H,
           SUM(CASE
                  WHEN T4.FABR_ID = 'TEST'
                       AND TAX_L >= 80
                  THEN
                     1
                  ELSE
                     NULL
               END)
              AS OVER80,
           SUM(CASE
                  WHEN     T4.FABR_ID = 'TEST'
                       AND TAX_L < 80
                       AND TAX_L IS NOT NULL
                  THEN
                     1
                  ELSE
                     NULL
               END)
              AS OVER80
    FROM   DBN1.F_BTS T1,
           DBN1.DA_CADASTRO T2,
           DBN1.D_TIME T3,
           DBN1.D_ENTITY_BTS T4
   WHERE       (T2.AA_CADASTRO_KEY = T1.AA_CADASTRO_KEY)
           AND (T3.TIME_KEY = T1.TIME_KEY)
           AND (T4.ENTITY_KEY = T1.ENTITY_KEY)
           AND (T2.COD_IBGE <> -1)
           AND (T3.HOUR BETWEEN 08 AND 23)
           AND (T3.REPORT_DATE_TIME BETWEEN TO_DATE ('27-09-2016 08:00:00',
                                                     'DD-MM-YYYY HH24:MI:SS')
                                        AND  TO_DATE ('27-09-2016 23:59:59',
                                                      'DD-MM-YYYY HH24:MI:SS'))
           AND (T4.FABR_ID IN ('TEST1', 'TEST2'))
           AND (T4.BTS_ID NOT IN ('', '*, -1'))
GROUP BY   T4.FABR_ID,
           T3.REPORT_DATE_TIME,
           T3.DAY_OF_WEEK,
           T4.REGIONAL_ID,
           T4.UF_ID,
           T4.BSC_ID,
           T2.COD_IBGE,
           T4.BTS_ID
ORDER BY   T4.FABR_ID,
           T3.REPORT_DATE_TIME,
           T3.DAY_OF_WEEK,
           T4.REGIONAL_ID,
           T4.UF_ID,
           T4.BSC_ID,
           T2.COD_IBGE,
           T4.BTS_ID;

【问题讨论】:

  • 您可以发布正在使用的完整查询吗?显然你不能在另一个sum 中使用sum
  • @vkp 查询范围很广,添加了一部分。我也有几个部分。
  • 无论使用何种数据库,这似乎都没有任何意义。您按八列分组,并为每个组计算TAX_L 作为表T1 中某些比率的SUM。然后,对于相同的 GROUPS,您想计算 TAX_L &gt;= 80 的次数?条件应单独适用于每一行;对于 GROUP,该条件要么为真,要么对于整个组为假,而不是逐行。查询应该计算什么? (想想与您的问题相关的列和值。)
  • @mathguy 此查询计算设备日志。每小时总览,累计。这些值将生成监控指标。我将删除总和并首先交付集群,然后是总和。

标签: sql oracle sum case


【解决方案1】:

我对您上面列出的构造完全不熟悉,但无论如何我都会尝试一下,因为您可以验证从一个系统到另一个系统的结果。我的猜测(这只是一个猜测)是您可以通过使用 CTE 获取第一个总和 (TAX_L) 来实现此结果,然后在主查询中使用该值来获取大于/小于 80 的值:

with yoda as (
  SELECT
    T4.FABR_ID, T3.REPORT_DATE_TIME, T3.DAY_OF_WEEK, T4.REGIONAL_ID,
    T4.UF_ID, T4.BSC_ID, T2.COD_IBGE, T4.BTS_ID,
    SUM (T1.M2251827) AS CAP_ALLOC,
    SUM(CASE
          WHEN T1.M2143831 > T1.M2460254
            THEN (T1.M2143831 * 100 / T1.M2143833)
          ELSE (T1.M2460254 * 100 / T1.M2460256)
        END) AS TAX_L,
    SUM (100 * T1.M2489212 / T1.M2489213) AS IUB_FRAME_LOST,
    SUM (T1.M1979632 * T1.M1979630) AS NUM_ACE,
    SUM (T1.M1977785 * T1.M1973189) AS DEN_ACE,
    SUM (T1.M2225994) AS THROUGHPUT_IUB_DOWNLINK_E,
    SUM ((T1.M2016166 + T1.M2016172 + T1.M1978319 + T1.M1978331)
          * 8 / 3600) AS THROUGHPUT_DADOS_TOTAL_H
  FROM
    DBN1.F_BTS T1,
    DBN1.DA_CADASTRO T2,
    DBN1.D_TIME T3,
    DBN1.D_ENTITY_BTS T4
  WHERE
    T2.AA_CADASTRO_KEY = T1.AA_CADASTRO_KEY
    AND T3.TIME_KEY = T1.TIME_KEY
    AND T4.ENTITY_KEY = T1.ENTITY_KEY
    AND T2.COD_IBGE <> -1
    AND T3.HOUR BETWEEN 08 AND 23
    AND T3.REPORT_DATE_TIME BETWEEN
      TO_DATE ('27-09-2016 08:00:00', 'DD-MM-YYYY HH24:MI:SS') and
      TO_DATE ('27-09-2016 23:59:59', 'DD-MM-YYYY HH24:MI:SS')
    AND T4.FABR_ID IN ('TEST1', 'TEST2')
    AND T4.BTS_ID NOT IN ('', '*, -1')
  GROUP BY
    T4.FABR_ID, T3.REPORT_DATE_TIME, T3.DAY_OF_WEEK, T4.REGIONAL_ID,
    T4.UF_ID, T4.BSC_ID, T2.COD_IBGE, T4.BTS_ID
)
select
  fabr_id, report_date_time, day_of_week, regional_id, uf_id, bsc_id,
  cod_ibge, bts_id, cap_alloc, tax_l, iub_frame_lost, num_ace,
  den_ace, throughput_uib_downlink_e, throughput_dados_total_h,
  SUM(CASE
        WHEN FABR_ID = 'TEST' AND TAX_L >= 80 THEN 1
        ELSE NULL
      END) AS OVER80,
  SUM(CASE
        WHEN FABR_ID = 'TEST' AND TAX_L < 80
          -- AND TAX_L IS NOT NULL  -- < 80 automatically means not null
          THEN 1
        ELSE NULL
      END) AS OVER80 -- you mean under 80?
from yoda
group by
  fabr_id, report_date_time, day_of_week, regional_id, uf_id, bsc_id,
  cod_ibge, bts_id, cap_alloc, tax_l, iub_frame_lost, num_ace,
  den_ace, throughput_uib_downlink_e, throughput_dados_total_h

一些杂项观察。

  1. “else null”通常不是必需的,但既然我们正在讨论这个主题,您的意思是“else 0”吗?反而? 1 + 1 + 1 + 1 + 空 + 1 = 空
  2. 您有两列别名为“超过 80”。我以为一个是“下”
  3. FIELD > x, FIELD 80,

同样,由于我从未见过在查询的同一部分引用聚合,因此我上面的 SQL 是有根据的猜测。

【讨论】:

  • 我太专注以至于忘记了 WITH。正如你所说,这个结构工作得很好,分两步删除了所有 NULL 子句,没有意义。感谢您的帮助。
猜你喜欢
  • 2018-11-29
  • 1970-01-01
  • 2016-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多