SELECT *
FROM a LEFT OUTER JOIN b
ON a.a1 = b.b1
那么b1和b2将为NULL其中a1的值与b1没有匹配的值。
我可以为b2提供默认值而不是NULL吗?请注意,COALESCE在这里行不通,因为我不希望默认值覆盖b2中存在与a1匹配的b1值的b2中的潜在NULL。
,即a和b为
CREATE TABLE a (a1)
AS VALUES (1),
(2),
(3) ;
CREATE TABLE b (b1,b2)
AS VALUES (1, 10),
(3, null) ;
a1 b1 | b2
--- --------
1 1 | 10
2 3 | NULL
3
,并且b2的默认值是100,我想得到结果
a1 | b1 | b2
---------------
1 | 1 | 10
2 | NULL | 100
3 | 3 | NULL
>在这种简单情况下,我可以通过查看输出中b1是否为NULL来“手工”完成。这是总体上最好的选择,还是有更标准,更整洁的方式?
#1 楼
SELECT a.a1,b.b1,
CASE WHEN b.b1 is NULL THEN 5 ELSE b.b2 END AS b2
FROM a LEFT OUTER JOIN b
ON a.a1 = b.b1
#2 楼
在这种情况下,我发现COALESCE非常有用。它将从列表中返回第一个非NULL值:SELECT
a.a1,
b.b1,
COALESCE (b.b2, 100) AS b2
FROM a
LEFT OUTER JOIN b
ON (a.a1 = b.b1);
评论
到目前为止,这是最好的答案。
–卢克
19/12/24在11:57
#3 楼
此问题的原始答案无法解释,因此让我们再来看看。使用
CASE
表达式使用此方法,我们利用我们在另一列中拥有另一个值该
IS NOT NULL
(在这种情况下为b.b1
)(如果该值为空)则表明连接失败。SELECT
a.a1,
b.b1,
CASE WHEN b.b1 is NULL THEN 100 ELSE b.b2 END AS b2
FROM a
LEFT OUTER JOIN b
ON (a.a1 = b.b1);
这将完全起作用,并生成您想要的确切内容。
使用子SELECT
不要使用此方法,它是一种构架思想。继续阅读。
如果没有这样可以利用的
NOT NULL
列,我们需要一些东西来创建一个可以对我们起作用的列... SELECT
a.a1,
b.b1,
CASE WHEN b.cond IS NULL THEN 100 ELSE b.b2 END AS b2
FROM a
LEFT OUTER JOIN (
SELECT true AS cond, b.*
FROM b
) AS b
ON (a.a1 = b.b1);
使用行比较
比较容易,尽管然后强制我们可以比较的错误值是比较行。在PostgreSQL中,该行具有表名的值。例如,
SELECT foo FROM foo
从表foo
返回类型为foo
的行(这是行类型)。在这里,我们测试一下ROW是否为空。只要每列IS NOT NULL
都可以使用。而且,如果表中的每列IS NULL
都在拖曳。SELECT
a.a1,
b.b1,
CASE WHEN b IS NULL THEN 100 ELSE b.b2 END AS b2
FROM a
LEFT OUTER JOIN b
ON (a.a1 = b.b1);
评论
CASE解决方案中使用的列b1不必是不可为空的。无论哪种情况,施工都可以进行。
–超立方体ᵀᴹ
17年3月20日在23:19
评论
我添加了一个标签以指示我将接受Postgres特定的答案。不过,如果可能的话,标准SQL将是首选。
–汤姆·埃利斯(Tom Ellis)
2014年1月15日19:46
@Kin:正如我的问题中所述,我知道“我可以通过查看输出中b1是否为NULL来“手工”完成。这是一般的最佳选择,还是有更标准,更整洁的方式?”
–汤姆·埃利斯(Tom Ellis)
2014年1月15日19:47
由于您要区分由于JOIN引起的NULL和“自然”存在的NULL,因此不可避免地必须检查b1。如果那是您“我可以“手动”完成”的意思,那么是唯一的方法。
– Mordechai
2014年1月15日19:54
@MorDeror:好的,我想我可能在想一种语法,例如“ LEFT OUTER JOIN ... ON ... DEFAULT b2 = ...”。
–汤姆·埃利斯(Tom Ellis)
2014年1月15日19:59
在没有解释的情况下,我很想拒绝这个投票。这个答案不符合DBA.SE的质量。
–埃文·卡洛尔(Evan Carroll)
17 Mar 20 '17在22:41