【问题标题】:I'm running into a duplication issue when joining multiple CTEs in Oracle在 Oracle 中加入多个 CTE 时遇到重复问题
【发布时间】:2019-07-26 15:10:54
【问题描述】:

我正在创建三个 CTE,我最终希望将它们连接在一起以创建一个汇总表。三个表中的两个包含相同的列,只是它们相加的项目不同(报价与新业务)。另一个表包含两个汇总列,报告排序和总成本,以及另一个字段的子类别,报告类型,它汇总到 LOB。

当我尝试将它们全部连接在一起并“重新汇总”这些字段时,就会出现问题。出于某种原因,即使我在 select 子句中使用了 DISTINCT 并且我认为我正确地加入了所有内容,我也会得到重复的值。

当我从 Total_Quotes 和 Total_NB 中删除 SUM 时,代码有效;但是,我希望将一条只有一个值的行相加就可以了。显然不是这样的。

WITH
MONTHLY_INVOICES AS
(SELECT DISTINCT
EXTRACT(YEAR FROM INVOICE_DATE) AS YEAR
,EXTRACT(MONTH FROM INVOICE_DATE) AS MONTH
,STATE
,REPORT_TYPE
,CASE WHEN REPORT_TYPE IN ('ADD', 'CCA', 'CLA', 'MVR', 'VIN') THEN 'AUTO'
      WHEN REPORT_TYPE IN ('CCP', 'CLP') THEN 'HOME'
      WHEN REPORT_TYPE IN ('DPF', 'NCF') THEN 'OTHER'
      END AS LOB
,SUM(TOTAL_ORDERS) AS TOTAL_ORDERS
,SUM(TOTAL_COST) AS TOTAL_COST
FROM
KAHJZK_VENDOR_INVOICE_TOTALS
GROUP BY
EXTRACT(YEAR FROM INVOICE_DATE)
,EXTRACT(MONTH FROM INVOICE_DATE)
,STATE
,REPORT_TYPE
,CASE WHEN REPORT_TYPE IN ('ADD', 'CCA', 'CLA', 'MVR', 'VIN') THEN 'AUTO'
      WHEN REPORT_TYPE IN ('CCP', 'CLP') THEN 'HOME'
      WHEN REPORT_TYPE IN ('DPF', 'NCF') THEN 'OTHER'
      END)

,MONTHLY_QT AS 
(SELECT DISTINCT
EXTRACT(YEAR FROM REPORT_DATE) AS YEAR
,EXTRACT(MONTH FROM REPORT_DATE) AS MONTH
,STATE
,LOB
,SUM(TOTAL_QUOTES) AS TOTAL_QTS
FROM KAHJZK_DAILY_QT_VOL
WHERE
EXTRACT(YEAR FROM REPORT_DATE) >= '2019'
GROUP BY
EXTRACT(YEAR FROM REPORT_DATE)
,EXTRACT(MONTH FROM REPORT_DATE)
,STATE
,LOB)

,MONTHLY_NB AS 
(SELECT DISTINCT
EXTRACT(YEAR FROM REPORT_DATE) AS YEAR
,EXTRACT(MONTH FROM REPORT_DATE) AS MONTH
,STATE
,LOB
,SUM(TOTAL_POLICIES) AS TOTAL_NB
FROM KAHJZK_DAILY_NB_VOL
WHERE
EXTRACT(YEAR FROM REPORT_DATE) >= '2019'
GROUP BY
EXTRACT(YEAR FROM REPORT_DATE)
,EXTRACT(MONTH FROM REPORT_DATE)
,STATE
,LOB)


SELECT DISTINCT
A.YEAR
,A.MONTH
,A.STATE
,A.LOB
,SUM(A.TOTAL_ORDERS)
,SUM(A.TOTAL_COST)
,SUM(B.TOTAL_QTS)
,SUM(C.TOTAL_NB)
FROM
MONTHLY_INVOICES A
LEFT OUTER JOIN MONTHLY_QT B
ON A.YEAR = B.YEAR
AND A.MONTH = B.MONTH
AND A.STATE = B.STATE
AND A.LOB = B.LOB
LEFT OUTER JOIN MONTHLY_NB C
ON A.YEAR = C.YEAR
AND A.MONTH = C.MONTH
AND A.STATE = C.STATE
AND A.LOB = C.LOB
GROUP BY
A.YEAR
,A.MONTH
,A.STATE
,A.LOB
ORDER BY
3,4,1,2;

当我将最后一部分更改为以下内容时,代码有效。:

SELECT DISTINCT
A.YEAR
,A.MONTH
,A.STATE
,A.LOB
,SUM(A.TOTAL_ORDERS)
,SUM(A.TOTAL_COST)
,B.TOTAL_QTS
,C.TOTAL_NB
FROM
MONTHLY_INVOICES A
LEFT OUTER JOIN MONTHLY_QT B
ON A.YEAR = B.YEAR
AND A.MONTH = B.MONTH
AND A.STATE = B.STATE
AND A.LOB = B.LOB
LEFT OUTER JOIN MONTHLY_NB C
ON A.YEAR = C.YEAR
AND A.MONTH = C.MONTH
AND A.STATE = C.STATE
AND A.LOB = C.LOB
GROUP BY
A.YEAR
,A.MONTH
,A.STATE
,A.LOB
,B.TOTAL_QTS
,C.TOTAL_NB
ORDER BY
3,4,1,2;

【问题讨论】:

标签: oracle


【解决方案1】:

您不应该将 DISTINCT 与 GROUP BY 一起使用。 GROUP BY 将返回 GROUP BY 中字段的不同组合,并进行适当的求和。所以我认为你想做这样的事情:

WITH MONTHLY_INVOICES AS (SELECT EXTRACT(YEAR FROM INVOICE_DATE) AS YEAR
                                ,EXTRACT(MONTH FROM INVOICE_DATE) AS MONTH
                                ,STATE
                                ,REPORT_TYPE
                                ,CASE WHEN REPORT_TYPE IN ('ADD', 'CCA', 'CLA', 'MVR', 'VIN') THEN 'AUTO'
                                      WHEN REPORT_TYPE IN ('CCP', 'CLP') THEN 'HOME'
                                      WHEN REPORT_TYPE IN ('DPF', 'NCF') THEN 'OTHER'
                                      END AS LOB
                                ,SUM(TOTAL_ORDERS) AS TOTAL_ORDERS
                                ,SUM(TOTAL_COST) AS TOTAL_COST
                            FROM KAHJZK_VENDOR_INVOICE_TOTALS
                            GROUP BY EXTRACT(YEAR FROM INVOICE_DATE)
                                    ,EXTRACT(MONTH FROM INVOICE_DATE)
                                    ,STATE
                                    ,REPORT_TYPE
                                    ,CASE WHEN REPORT_TYPE IN ('ADD', 'CCA', 'CLA', 'MVR', 'VIN') THEN 'AUTO'
                                          WHEN REPORT_TYPE IN ('CCP', 'CLP') THEN 'HOME'
                                          WHEN REPORT_TYPE IN ('DPF', 'NCF') THEN 'OTHER'
                                          END),
     MONTHLY_QT AS (SELECT EXTRACT(YEAR FROM REPORT_DATE) AS YEAR
                          ,EXTRACT(MONTH FROM REPORT_DATE) AS MONTH
                          ,STATE
                          ,LOB
                          ,SUM(TOTAL_QUOTES) AS TOTAL_QTS
                      FROM KAHJZK_DAILY_QT_VOL
                      WHERE EXTRACT(YEAR FROM REPORT_DATE) >= 2019
                      GROUP BY EXTRACT(YEAR FROM REPORT_DATE)
                              ,EXTRACT(MONTH FROM REPORT_DATE)
                              ,STATE
                              ,LOB),
     MONTHLY_NB AS (SELECT EXTRACT(YEAR FROM REPORT_DATE) AS YEAR
                          ,EXTRACT(MONTH FROM REPORT_DATE) AS MONTH
                          ,STATE
                          ,LOB
                          ,SUM(TOTAL_POLICIES) AS TOTAL_NB
                     FROM KAHJZK_DAILY_NB_VOL
                     WHERE EXTRACT(YEAR FROM REPORT_DATE) >= 2019
                     GROUP BY EXTRACT(YEAR FROM REPORT_DATE)
                             ,EXTRACT(MONTH FROM REPORT_DATE)
                             ,STATE
                             ,LOB)
SELECT A.YEAR
      ,A.MONTH
      ,A.STATE
      ,A.LOB
      ,SUM(A.TOTAL_ORDERS)
      ,SUM(A.TOTAL_COST)
      ,SUM(B.TOTAL_QTS)
      ,SUM(C.TOTAL_NB)
  FROM MONTHLY_INVOICES A
  LEFT OUTER JOIN MONTHLY_QT B
    ON A.YEAR = B.YEAR
   AND A.MONTH = B.MONTH
   AND A.STATE = B.STATE
   AND A.LOB = B.LOB
  LEFT OUTER JOIN MONTHLY_NB C
   ON A.YEAR = C.YEAR
  AND A.MONTH = C.MONTH
  AND A.STATE = C.STATE
  AND A.LOB = C.LOB
  GROUP BY A.YEAR
          ,A.MONTH
          ,A.STATE
          ,A.LOB
  ORDER BY 3,4,1,2;

与您应该使用数字的EXTRACT 的结果(例如2019)进行比较时,您还使用了字符串(例如'2019') - 我已经更新了。

试一试,看看它是否符合您的要求。

【讨论】:

  • 感谢您的回答和格式化!它看起来仍然给我重复。
  • 我以为我已经通过创建表而不是 CTE 解决了这个问题。原来我不小心留下了从引号和 NB 中删除 SUM 的旧修复。
  • 我仍然收到重复。我从第一个 CTE 中删除了 REPORT_TYPE 并解决了问题;但是我想,因为我没有将它带入我的最终 SELECT 语句,所以其他两个表不会加入(?)多行。我觉得我已经使用临时表在 SQL Server 中编写了大量这样的查询,但没有遇到这个问题。但我一定会小心前进的。
【解决方案2】:
  1. 您必须提供一个或多个列来唯一标识每个表中的每一行。
  2. 您必须提供一种方法,可以将一个表中唯一标识的行连接到另一个表中唯一标识的行。

未能解决上面列出的两个项目将导致结果集是选择标准的笛卡尔积(也称为叉积)。

编辑(回复评论 1)
distinct 不会影响连接产生的叉积。 如果你得到一个交叉产品, 那么您可能在连接的一侧选择行 与另一侧的任何行都不匹配。

例如, 试试select a.field, b.field from table 1 a, table 2 b (即不加入,只列出两个表) 你会得到一个叉积。

如果您在添加 left join 子句。

【讨论】:

  • 感谢您的快速回答!我想通过加入 YEAR、MONTH、STATE 和 LOB 并使用 SELECT DISTINCT 我会阻止一对多加入。我还是有点困惑。即使我没有将它作为最终 SELECT 的一部分引入,第一个 CTE 中是否存在 REPORT_TYPE 也会导致问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多