假设我有表a(具有a1列)和b(具有b1和b2列),并且执行了左外部联接

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


评论


我添加了一个标签以指示我将接受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

#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