【问题标题】:Full outer join with "case when" and subquery带有“case when”和子查询的完全外连接
【发布时间】:2017-07-07 01:13:57
【问题描述】:

我有一个完整的外连接查询,在 oracle 中有 case when 和 sub 查询。我想要完成的是汇总同一张表中的当年数据和上一年数据,以便进行比较。但是,我的 FULL OUTER JOIN 充当内部连接,不会返回当年和上一年的空值。

这是我的代码:

SELECT
   SQ1.CHANNEL,
   SQ1.SHORT,
   SQ1.NAME,
   SQ1.RDC,
   SQ1.CY_APPROVED_COUNT,
   SQ2.PY_APPROVED_COUNT,
   SQ1.CY_APPROVED_VOLUME,
   SQ2.PY_APPROVED_VOLUME,
   SQ1.CY_DECLINED_COUNT,
   SQ2.PY_DECLINED_COUNT,
   SQ1.CY_DECLINED_VOLUME,
   SQ2.PY_DECLINED_VOLUME,
   SQ1.CY_RETURNED_COUNT,
   SQ2.PY_RETURNED_COUNT,
   SQ1.CY_RETURNED_VOLUME,
   SQ2.PY_RETURNED_VOLUME
FROM ( SELECT 
          CHANNEL,
          SHORT,
          NAME,
          RDC,
          SUM (CASE WHEN STATUS = 'Approved' THEN  APP_COUNTS ELSE 0 END) AS CY_APPROVED_COUNT,
          SUM (CASE WHEN STATUS = 'Approved' THEN  PROJ_VOL ELSE 0 END) AS CY_APPROVED_VOLUME,
          SUM (CASE WHEN STATUS = 'Declined' THEN  APP_COUNTS ELSE 0 END) AS CY_DECLINED_COUNT,
          SUM (CASE WHEN STATUS = 'Declined' THEN  PROJ_VOL ELSE 0 END) AS CY_DECLINED_VOLUME,
          SUM (CASE WHEN STATUS = 'Returned' THEN  APP_COUNTS ELSE 0 END) AS CY_RETURNED_COUNT,
          SUM (CASE WHEN STATUS = 'Returned' THEN  PROJ_VOL ELSE 0 END) AS CY_RETURNED_VOLUME
       FROM WFRT_MSP_SP_MTD
       WHERE PERIOD >= TO_DATE('2016/02/01', 'yyyy/mm/dd')
         AND PERIOD <= TO_DATE('2016/02/13','yyyy/mm/dd')
         AND CHANNEL = 'MSP'
         AND RDC = 'BASE'
       GROUP BY 
          CHANNEL,
          SHORT,
          NAME,
          RDC 
) SQ1
-- NOT CORRECTLY SHOWING NULL VALUES
FULL OUTER JOIN  

( SELECT 
     CHANNEL,
     SHORT,
     NAME,
     RDC,
     SUM (CASE WHEN STATUS = 'Approved' THEN  APP_COUNTS ELSE 0 END) AS PY_APPROVED_COUNT,
     SUM (CASE WHEN STATUS = 'Approved' THEN  PROJ_VOL ELSE 0 END) AS PY_APPROVED_VOLUME,
     SUM (CASE WHEN STATUS = 'Declined' THEN  APP_COUNTS ELSE 0 END) AS PY_DECLINED_COUNT,
     SUM (CASE WHEN STATUS = 'Declined' THEN  PROJ_VOL ELSE 0 END) AS PY_DECLINED_VOLUME,
     SUM (CASE WHEN STATUS = 'Returned' THEN  APP_COUNTS ELSE 0 END) AS PY_RETURNED_COUNT,
     SUM (CASE WHEN STATUS = 'Returned' THEN  PROJ_VOL ELSE 0 END) AS PY_RETURNED_VOLUME
FROM WFRT_MSP_SP_MTD
WHERE PERIOD >= TO_DATE('2015/02/01', 'yyyy/mm/dd')
   AND PERIOD <= TO_DATE('2015/02/13','yyyy/mm/dd')
   AND CHANNEL = 'MSP'
   AND RDC = 'BASE'
GROUP BY 
   CHANNEL,
   SHORT,
   NAME,
   RDC
) SQ2
ON sq1.short = sq2.short
;

如果可以的话,请帮忙。

【问题讨论】:

  • 可能有助于使用缩进以提高可读性

标签: sql oracle join subquery outer-join


【解决方案1】:

只使用条件聚合:

SELECT CHANNEL, SHORT, NAME, RDC,
       SUM(CASE WHEN this_year = 1 AND STATUS = 'Approved' THEN  APP_COUNTS ELSE 0 END) AS CY_APPROVED_COUNT,
       SUM(CASE WHEN this_year = 1 AND STATUS = 'Approved' THEN  PROJ_VOL ELSE 0 END) AS cY_APPROVED_VOLUME,
       SUM(CASE WHEN this_year = 1 AND STATUS = 'Declined' THEN  APP_COUNTS ELSE 0 END) AS CY_DECLINED_COUNT,
       SUM(CASE WHEN this_year = 1 AND STATUS = 'Declined' THEN  PROJ_VOL ELSE 0 END) AS CY_DECLINED_VOLUME,
       SUM(CASE WHEN this_year = 1 AND STATUS = 'Returned' THEN  APP_COUNTS ELSE 0 END) AS CY_RETURNED_COUNT,
       SUM(CASE WHEN this_year = 1 AND STATUS = 'Returned' THEN  PROJ_VOL ELSE 0 END) AS CY_RETURNED_VOLUME,
       SUM(CASE WHEN prev_year = 1 AND STATUS = 'Approved' THEN  APP_COUNTS ELSE 0 END) AS PY_APPROVED_COUNT,
       SUM(CASE WHEN prev_year = 1 AND STATUS = 'Approved' THEN  PROJ_VOL ELSE 0 END) AS PY_APPROVED_VOLUME,
       SUM(CASE WHEN prev_year = 1 AND STATUS = 'Declined' THEN  APP_COUNTS ELSE 0 END) AS PY_DECLINED_COUNT,
       SUM(CASE WHEN prev_year = 1 AND STATUS = 'Declined' THEN  PROJ_VOL ELSE 0 END) AS PY_DECLINED_VOLUME,
       SUM(CASE WHEN prev_year = 1 AND STATUS = 'Returned' THEN  APP_COUNTS ELSE 0 END) AS PY_RETURNED_COUNT,
       SUM(CASE WHEN prev_year = 1 AND STATUS = 'Returned' THEN  PROJ_VOL ELSE 0 END) AS PY_RETURNED_VOLUME
FROM (SELECT msm.*,
             (CASE WHEN PERIOD >= DATE '2015-02-01' AND
                        PERIOD <= '2015-02-13'
                   THEN 1 ELSE 0
              END) as prev_year,
             (CASE WHEN PERIOD >= DATE '2016-02-01' AND
                        PERIOD <= '2016-02-13'
                   THEN 1 ELSE 0
              END) as this_year
      FROM WFRT_MSP_SP_MTD msm
     ) msm
WHERE CHANNEL = 'MSP' AND RDC = 'BASE'
GROUP BY CHANNEL, SHORT, NAME, RDC;

【讨论】:

  • 我收到 ORA-00904: "MSM": invalid identifier 00904. 00000 - "%s: invalid identifier"
  • @dmoses 只需将 msm 别名从子查询的右括号外移到其中(即,您需要为子查询内的表命名,而不是子查询本身)。
  • @Boneist 我在子查询“wfrt_msp_sp_mtd”中将“msm”移到表旁边,并收到错误消息“文字与格式字符串不匹配”
  • @dmoses 似乎 DATE 文字关键字被意外遗漏了几个日期文字;确保 PERIOD &lt;= '... 变为 PERIOD &lt;= DATE '...
猜你喜欢
  • 2022-01-02
  • 2018-11-15
  • 2019-05-24
  • 2022-12-15
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 2017-05-30
  • 2021-12-22
相关资源
最近更新 更多