5

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

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

src_t1 id1_t1 id2_t1 val_t1 src_t2 id1_t2 id2_t2 val_t2

                                        bzz 4
哇 100 bww 1
axx 200 bxx 2
哎呀 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)

我也尝试将子句中的条件也移动WHEREON子句中。

TIA。

4

2 回答 2

6

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

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

于 2013-06-22T16:27:57.687 回答
5

实际上,如果使用 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
;
于 2013-06-23T14:56:43.427 回答