【问题标题】:Full Join on Group完全加入群组
【发布时间】:2015-06-10 09:28:30
【问题描述】:

我的查询遇到逻辑问题。

我有两个表 Table1Table2,其中Table1 包括:

  • value 待总结
  • Id 被分组
  • Code 持有Table2的外键

Table2

组成
  • Code
  • Des代码文字说明

我要做的是,按Table1.Id 分组,在Table2.Code 上完全加入,但是,对于每个结果组,我想为查询生成的每个组显示 Table2 中的所有行。

示例代码:

SELECT
    Table2.Code, Table1.Id, Table2.DES, 
    SUM(Table1.Value) AS SUM_VAL
FROM 
(
    SELECT 'A' AS Code, 1 AS Id, 10 AS Value FROM DUAL UNION
    SELECT 'A' AS Code, 2 AS Id, 20 AS Value FROM DUAL UNION
    SELECT 'B' AS Code, 1 AS Id, 10 AS Value FROM DUAL UNION
    SELECT 'B' AS Code, 1 AS Id, 30 AS Value FROM DUAL UNION
    SELECT 'B' AS Code, 2 AS Id, 50 AS Value FROM DUAL UNION
    SELECT 'C' AS Code, 1 AS Id, 40 AS Value FROM DUAL UNION
    SELECT 'C' AS Code, 2 AS Id, 60 AS Value FROM DUAL UNION
    SELECT 'D' AS Code, 1 AS Id, 20 AS Value FROM DUAL

) Table1
FULL JOIN
(
    SELECT 'A' AS Code, 'This is A' AS DES FROM DUAL UNION
    SELECT 'B' AS Code, 'This is B' AS DES FROM DUAL UNION
    SELECT 'C' AS Code, 'This is C' AS DES FROM DUAL UNION
    SELECT 'D' AS Code, 'This is D' AS DES FROM DUAL
) Table2
ON Table1.Code = Table2.Code
GROUP BY
    Table2.Code, Table1.Id, Table2.DES
ORDER BY
    Table2.Code, Table1.Id ASC

结果:

A   1   This is A   10
A   2   This is A   20
B   1   This is B   40
B   2   This is B   50
C   1   This is C   40
C   2   This is C   60
D   1   This is D   20

要求的结果:

A   1   This is A   10
A   2   This is A   20
B   1   This is B   40
B   2   This is B   50
C   1   This is C   40
C   2   This is C   60
D   1   This is D   20
D   2   This is D   0    <- This is the target

【问题讨论】:

  • coalesce(Table1.Code, Table2.Code) 在选择和分组方式中?
  • 这与问题有什么关系?
  • 在 table1 中没有命中时改进了全外连接结果。

标签: sql oracle oracle10g full-outer-join


【解决方案1】:

您必须以某种方式显示值对 (D,2) 例如。通过制作一个包含可能值的代码列表并将NULL 转换为0

  SELECT code.code,
         code.id,
         des.des,
         NVL (SUM (val.value), 0) sum_val
    FROM (SELECT 'A' code, 1 id FROM DUAL
          UNION
          SELECT 'A', 2 FROM DUAL
          UNION
          SELECT 'B', 1 FROM DUAL
          UNION
          SELECT 'B', 2 FROM DUAL
          UNION
          SELECT 'C', 1 FROM DUAL
          UNION
          SELECT 'C', 2 FROM DUAL
          UNION
          SELECT 'D', 1 FROM DUAL
          UNION
          SELECT 'D', 2 FROM DUAL) code
         INNER JOIN (SELECT 'A' code, 'This is A' des FROM DUAL
                     UNION
                     SELECT 'B', 'This is B' FROM DUAL
                     UNION
                     SELECT 'C', 'This is C' FROM DUAL
                     UNION
                     SELECT 'D', 'This is D' FROM DUAL) des
            ON code.code = des.code
         LEFT OUTER JOIN (SELECT 'A' code, 1 id, 10 VALUE FROM DUAL
                          UNION ALL
                          SELECT 'A', 2, 20 FROM DUAL
                          UNION ALL
                          SELECT 'B', 1, 10 FROM DUAL
                          UNION ALL
                          SELECT 'B', 1, 30 FROM DUAL
                          UNION ALL
                          SELECT 'B', 2, 50 FROM DUAL
                          UNION ALL
                          SELECT 'C', 1, 40 FROM DUAL
                          UNION ALL
                          SELECT 'C', 2, 60 FROM DUAL
                          UNION ALL
                          SELECT 'D', 1, 20 FROM DUAL) val
            ON code.code = val.code AND code.id = val.id
GROUP BY code.code, code.id, des.des
ORDER BY code, id

UNION ALL 用于val,因为可能会出现重复。

不需要FULL OUTER JOIN

【讨论】:

  • 虽然您建议的解决方案改变了查询的整个结构,这在我的原始代码中是不可能的,但上面的代码只是模仿我所面临的情况的示例,还有很多更复杂的代码,但你给了我如何解决问题的提示,谢谢。我会在几分钟内更新问题。
  • 在完整的join语句中(原代码):我选择了1和2,分别用ABC 和 D 为我提供 ABC 的所有可能性D12,因此 Table2 现在包含 CodeTextId,然后在 join filter 之间Table1Table2,我在条件中也添加了 and Table1.id = table2.id 这解决了问题
  • 如果只有代码 1 和 2 是相关的,这听起来很合理。否则,您可以考虑 Gordon Linoff 建议的动态方法。
【解决方案2】:

如果您想要 id 和 value 的所有组合,则使用 cross join 获取行并使用 left join 引入其余值:

select t2.code, i.value, t2.desc, coalesce(cnt, 0) as cnt
from (select distinct id from table1) i cross join
     table2 t2 left join
     (select id, value, count(*) as cnt
      from table1
      group by id, value
     ) iv
     on iv.id = i.id and iv.code = t2.code

这应该比手动列出所有组合要简单得多。

【讨论】:

  • 谢谢,我已经以类似的方式解决了这个问题,请查看我在 Jon Tofte-Hansen 回答中的评论
  • @simsim 。 . .此解决方案的关键是使用cross join 生成您想要的所有,然后使用left join 添加适当的列。
【解决方案3】:
SELECT
    Table2.Code, Table2.NAT, Table2.DES, 
    SUM(Table1.Value) AS SUM_VAL
FROM 
(
    SELECT 'A' AS Code, 'QA' AS Id, 10 AS Value FROM DUAL UNION
    SELECT 'A' AS Code, 'NQA' AS Id, 20 AS Value FROM DUAL UNION
    SELECT 'B' AS Code, 'QA' AS Id, 10 AS Value FROM DUAL UNION
    SELECT 'B' AS Code, 'QA' AS Id, 30 AS Value FROM DUAL UNION
    SELECT 'B' AS Code, 'NQA' AS Id, 50 AS Value FROM DUAL UNION
    SELECT 'C' AS Code, 'QA' AS Id, 40 AS Value FROM DUAL UNION
    SELECT 'C' AS Code, 'NQA' AS Id, 60 AS Value FROM DUAL UNION
    SELECT 'D' AS Code, 'QA' AS Id, 20 AS Value FROM DUAL

) Table1
FULL JOIN
(
    SELECT 'QA' NAT,'A' AS Code, 'This is A' AS DES FROM DUAL UNION
    SELECT 'QA' NAT,'B' AS Code, 'This is B' AS DES FROM DUAL UNION
    SELECT 'QA' NAT,'C' AS Code, 'This is C' AS DES FROM DUAL UNION
    SELECT 'QA' NAT,'D' AS Code, 'This is D' AS DES FROM DUAL
    UNION
    SELECT 'NQA' NAT,'A' AS Code, 'This is A' AS DES FROM DUAL UNION
    SELECT 'NQA' NAT,'B' AS Code, 'This is B' AS DES FROM DUAL UNION
    SELECT 'NQA' NAT,'C' AS Code, 'This is C' AS DES FROM DUAL UNION
    SELECT 'NQA' NAT,'D' AS Code, 'This is D' AS DES FROM DUAL
) Table2
on TABLE2.NAT = TABLE1.ID
      AND Table2.Code= Table1.Code
GROUP BY
    Table2.Code, Table2.NAT, Table2.DES
ORDER BY
    Table2.Code, Table2.NAT ASC

【讨论】:

    猜你喜欢
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 2011-09-14
    • 2015-04-07
    • 2016-02-10
    相关资源
    最近更新 更多