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


21

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

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

b1とb2は、a1の値に一致するb1の値がない場合、NULLになります。

NULLの代わりにb2のデフォルト値を提供できますか?私はのでCOALESCEが、ここでは動作しないことに注意していないがどこB2の潜在的なNULLを上書きするデフォルト値をしたいです 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

そして、例えば100のb2のデフォルトは、結果を取得したい

a1 | b1   | b2
---------------
1  |  1   | 10
2  | NULL | 100
3  |  3   | NULL

この単純なケースでは、出力でb1がNULLであるかどうかを調べることにより、「手動で」それを行うことができます。それは一般的に最良の選択肢ですか、それとももっと標準的でよりきれいな方法がありますか?

回答:


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製品または方言を示しません)。part:[b2]=CASE WHEN ... ENDは無効な(標準)SQL式です。
a_horse_with_no_name 14年

Postgres固有の回答を受け入れることを示すタグを追加しました。それでも、可能であれば標準SQLが優先されます。
トム・エリス

@Kin:私の質問で述べたように、「出力でb1がNULLであるかどうかを調べることで「手作業で」できることを知っています。それが一般的に最良のオプションですか、またはより標準的でよりきちんとした方法がありますか?」
トム・エリス

3
JOINのために発生するNULLと「自然に」存在するNULLを区別する必要があるため、b1を調べる必要があることは避けられません。それがあなたが「私が「手で」できる」という意味なら、はいよりも、それが唯一の方法です。
モルデカイ14年

@MorDeror:OK、「LEFT OUTER JOIN ... ON ... DEFAULT b2 = ...」などの構文があるかもしれないと考えていたと思います。
トム・エリス

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使用される列は、CASEnull不可である必要はありません。どちらの場合でも構築は機能します。
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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.