【问题标题】:Full Outer Self Join [duplicate]完全外部自联接 [重复]
【发布时间】:2013-06-22 16:11:23
【问题描述】:

问题是返回包含空值的行。下面是创建表并使用示例数据填充表的 SQL 代码。

我期待下面的内容,但查询没有显示具有空值的两行。

src_t1 id1_t1 id2_t1 val_t1 src_t2 id1_t2 id2_t2 val_t2 bz z 4 a w w 100 b w w 1 a x x 200 b x x 2 yy 300

数据:

CREATE TABLE sample (
    src VARCHAR(6)
    ,id1 VARCHAR(6)
    ,id2 VARCHAR(6)
    ,val FLOAT
);

INSERT INTO sample (src, id1, id2, val)
VALUES ('a', 'w', 'w', 100)
      ,('b', 'w', 'w', 1) 
      ,('a', 'x', 'x', 200)
      ,('b', 'x', 'x', 2) 
      ,('a', 'y', 'y', 300)
      ,('b', 'z', 'z', 4) 
;

这是我的测试查询。当 t1.src = 'a' 和 t1.id1 = 'y' 或 t2.src = 'b' 和 t2.id1 = 'z' 时,它不会显示结果。

为什么?

什么是正确的查询?

SELECT t1.src, t1.id1, t1.id2, t1.val
  ,t2.src as src2, t2.id1, t2.id2, t2.val
FROM sample t1 FULL OUTER JOIN sample t2
  ON t1.id1 = t2.id1 AND t1.id2 = t2.id2
WHERE (t1.src = 'a' AND t2.src = 'b') 
  OR (t1.src IS NULL AND t1.id1 IS NULL AND t1.id2 IS NULL)
  OR (t2.src IS NULL AND t2.id1 IS NULL AND t2.id2 IS NULL)

我还尝试将WHERE 子句中的条件也移动到ON 子句。

TIA。

【问题讨论】:

  • 为了调整我在其他问题中的回答中的 SQL,这里看起来像 from (select * from sample where src = 'a') t1 full outer join (select * from sample where src = 'b') t2 on t2.id1 = t1.id1 and t2.id2 = t1.id2:sqlfiddle.com/#!6/e7b1e/3
  • @hvd 谢谢。这样可行。当您知道如何操作时,如此简单。
  • @hvd 如果您将其作为答案发布,我将很乐意接受。
  • 谢谢,我很感激,但我故意只将它作为评论发布:重复的问题不应该得到重复的答案,如果他们可以简单地获得指向已经在别处给出的答案的指针。 :)

标签: tsql


【解决方案1】:

其实我觉得如果使用 CTE 解决方案会更干净一些:

WITH A AS (
  select * from sample where src='a'
),
B AS (
  select * from sample where src='b'
)
SELECT *
FROM A FULL OUTER JOIN B
    ON A.ID1 = B.ID1 AND A.ID2 = B.ID2
;

【讨论】:

    【解决方案2】:

    WHERE 子句计算得太晚,有效地将您的查询转换为内部联接。

    相反,使用正确的 JOIN 语法编写您的查询:

    SELECT t1.src, t1.id1, t1.id2, t1.val
      ,t2.src as src2, t2.id1, t2.id2, t2.val
    FROM (
        select * from sample
        where src='a'
    ) t1 FULL OUTER JOIN (
        select * from sample 
        where src='b'
    )  t2
      ON t1.id1 = t2.id1 AND t1.id2 = t2.id2
    

    产生这个结果集:

    src  id1  id2  val         src2 id1  id2  val
    ---- ---- ---- ----------- ---- ---- ---- -----------
    a    w    w    100         b    w    w    1
    a    x    x    200         b    x    x    2
    NULL NULL NULL NULL        b    z    z    4
    a    y    y    300         NULL NULL NULL NULL
    

    更新
    还要注意使用两个子查询来清楚地将源表分成两个不同的 relvar。我在第一次提交时错过了这一分钟。

    【讨论】:

    • -1 因为问题明确包含预期的输出,这与您的输出不同。
    • @hvd 是正确的。 Pieter,请注意您的结果如何在两个源列中包含“a”和“b”值。关键是一侧只有“a”,另一侧只有“b”。
    • 已删除反对票。虽然无害,但您最后一行的and (t1.src = 'a' AND t2.src = 'b') 现在是多余的。
    • @PieterGeerkens,and (t1.src = 'a' AND t2.src = 'b') 不是必需的(并且可能不起作用),因为这两个表表达式已经根据所需条件进行了过滤。
    • @Karl:这就是 WHERE 子句和 JOIN 子句中的条件之间的区别。正如您所注意到的,将该限制放在 WHERE 子句中有效地转换为 INNER JOIN;但是,我将它放在 JOIN 子句中,它不会产生这种效果。
    猜你喜欢
    • 2011-07-26
    • 1970-01-01
    • 2017-08-04
    • 2014-08-21
    • 1970-01-01
    • 2021-11-17
    相关资源
    最近更新 更多