web-dev-qa-db-ja.com

左外部結合にデフォルトを提供できますか?

テーブルa(列a1)とb(列b1とb2)があり、左外部結合を実行するとします。

SELECT *
FROM a LEFT OUTER JOIN b
ON a.a1 = b.b1

次に、b1とb2はNULLになり、a1の値にはb1の一致する値がありません。

NULLの代わりにb2のデフォルト値を指定できますか? COALESCEはここでは機能しないことに注意してください。私はしないでください b2の潜在的なNULLをデフォルト値で上書きしたいためですis a1に一致するb1の値。

つまり、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であるかどうかを確認することにより、「手動」で実行できます。それは一般的に最良の選択肢ですか、それとももっと標準的でよりきれいな方法がありますか?

22
Tom Ellis
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
25
Mordechai

その場合COALESCEは非常に役立つと思います。リストから最初のNULL以外の値を返します。

SELECT
 a.a1,
 b.b1,
 COALESCE (b.b2, 100) AS b2
FROM a
LEFT OUTER JOIN b
  ON (a.a1 = b.b1);
4
Rob

この質問に対する最初の答えは説明がつかなかったので、これをもう一度試してみましょう。

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では、行にはテーブルの名前による値があります。たとえば、SELECT foo FROM fooは、テーブルfooから、タイプfoo(行タイプ)の行を返します。ここでは、そのROWがnullかどうかをテストします。これは、everyIS 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);
2
Evan Carroll