我可以为左外部联接提供默认设置吗?


21

假设我有表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不会在这里工作,因为我希望默认值来覆盖潜在的NULL在B2那里 B1匹配A1的值。

也就是说,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来“手工”完成。这是总体上最好的选择,还是有更标准,更整洁的方式?

Answers:


23
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
仅在标记问题时使用ANSI SQL sql(这表示“ SQL查询语言”。该标记不表示任何特定的DBMS产品或方言)。该部分:[b2]=CASE WHEN ... END是无效的(标准)SQL表达式。
a_horse_with_no_name 2014年

我添加了一个标签,表示我将接受Postgres特定的答案。不过,如果可能的话,标准SQL将是首选。
汤姆·埃利斯

@Kin:正如我的问题中所述,我知道“我可以通过查看输出中b1是否为NULL来“手工”完成。这是一般的最佳选择,还是有一种更标准,更整洁的方式?”
汤姆·埃利斯

3
由于您要区分由于JOIN引起的NULL和“自然”存在的NULL,因此不可避免地必须检查b1。如果那是您“我可以“手动”完成”的意思,那是唯一的方法。
Mordechai 2014年

@MorDeror:好的,我想我可能在想一种语法,例如“ LEFT OUTER JOIN ... ON ... DEFAULT b2 = ...”。
Tom Ellis 2014年

2

这个问题的原始答案无法解释,因此让我们再试一下。

使用CASE陈述

使用此方法,我们利用了在不同的列中具有另一个值的IS NOT NULL情况在这种情况下,b.b1如果该值为null,则我们知道联接失败。

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中,该行具有表名的值。例如,从table 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);

解决方案中b1使用的列CASE不必为空。无论哪种情况,施工都可以进行。
ypercubeᵀᴹ

1

在这种情况下,我发现COALESCE非常有用。它将从列表中返回第一个非NULL值:

SELECT
 a.a1,
 b.b1,
 COALESCE (b.b2, 100) AS b2
FROM a
LEFT OUTER JOIN b
  ON (a.a1 = b.b1);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.