PostgreSQLでは、SQLステートメントを使用して2つの列を結合し、それらから新しい列を作成したいと思います。
concat(...)
の使用を考えていますが、もっと良い方法はありますか?
これを行う最良の方法は何ですか?
一般的に、私は @ kgrittnのアドバイス に同意します。頑張れ。
ただし、 concat()
に関する基本的な質問に対処するには、新しい関数concat()
null値を処理する必要がある場合に便利です-そして、nullはあなたの質問でも参照するものでも除外されていません。
null値を除外できる場合、古き良き(SQL標準)連結演算子 _||
_ はまだ最良の選択、および @ luis 'answer は問題ありません。
_SELECT col_a || col_b;
_
Ifいずれかの列がヌルになる可能性がある場合、その場合、結果はヌルになります。 COALESCE
で防御できます:
_SELECT COALESCE(col_a, '') || COALESCE(col_b, '');
_
しかし、それはより多くの議論ですぐに退屈になります。ここでconcat()
が入力され、neverは、all引数がnullであってもnullを返しません。 ドキュメントごと :
NULL引数は無視されます。
_SELECT concat(col_a, col_b);
_
両方の選択肢のremaining corner caseは、all入力列はnullです。この場合、空の文字列_''
_を取得しますが、代わりにnullが必要な場合があります(少なくとも私はそうします)。 1つの可能な方法:
_SELECT CASE
WHEN col_a IS NULL THEN col_b
WHEN col_b IS NULL THEN col_a
ELSE col_a || col_b
END
_
これは、より多くの列でより複雑になります。繰り返しますが、concat()
を使用しますが、特別な条件のチェックを追加します。
_SELECT CASE WHEN (col_a, col_b) IS NULL THEN NULL
ELSE concat(col_a, col_b) END;
_
これはどのように機能しますか?
_(col_a, col_b)
_は、行タイプの式ROW (col_a, col_b)
の略記法です。また、行タイプは、all列がnullの場合にのみnullです。詳細な説明:
また、 concat_ws()
を使用して、要素間にセパレータを追加します(__ws
_ .. "withセパレータ」)。
ケビンの答えのような表現:
_SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
_
postgreSQL 8.3でnull値を準備するのは面倒です(concat()
なし)。 (多くの)1つの方法:
_SELECT COALESCE(
CASE
WHEN $1.zipcode IS NULL THEN $1.city
WHEN $1.city IS NULL THEN $1.zipcode
ELSE $1.zipcode || ' - ' || $1.city
END, '')
|| COALESCE(', ' || $1.state, '');
_
STABLE
のみですただし、concat()
およびconcat_ws()
はSTABLE
ではなくIMMUTABLE
関数であり、データ型出力関数(_timestamptz_out
_など)を呼び出すことができるため、注意してください。 )ロケール設定に依存します。 トムレーンによる説明
これにより、インデックス式での直接使用が禁止されます。結果が実際に不変であることを知っている場合、IMMUTABLE
関数ラッパーでこれを回避できます。ここの例:
そのように参照するために列を保存する必要はありません。これを試して:
設定する:
CREATE TABLE tbl
(zipcode text NOT NULL, city text NOT NULL, state text NOT NULL);
INSERT INTO tbl VALUES ('10954', 'Nanuet', 'NY');
「適切なもの」があることがわかります。
\pset border 2
SELECT * FROM tbl;
+ --------- + -------- + ------- + |郵便番号|市|状態| + --------- + -------- + ------- + | 10954 |ナニュエット| NY | + --------- + -------- + ------- +
ここで、テーブルのレコードタイプを唯一のパラメータとして使用する目的の「列名」を持つ関数を追加します。
CREATE FUNCTION combined(rec tbl)
RETURNS text
LANGUAGE SQL
AS $$
SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
$$;
これにより、次のようにテーブル名またはエイリアスが指定されている限り、テーブルの列であるかのように使用できる関数が作成されます。
SELECT *, tbl.combined FROM tbl;
次のように表示されます:
+ --------- + -------- + ------- + ----------------- --- + |郵便番号|市|状態|結合| + --------- + -------- + ------- + --------------- ----- + | 10954 |ナニュエット| NY | 10954-ニューヨーク州ナニュエット| + --------- + -------- + ------- + ----------- --------- +
PostgreSQLは最初に実際の列をチェックしますが、見つからない場合、識別子がリレーション名またはエイリアスで修飾されている場合、上記のような関数を探し、行を引数として実行して戻ります。結果が列であるかのように。そのような「生成された列」でインデックスを作成することもできます。
重複データの各行で余分なスペースを使用したり、すべての挿入および更新でトリガーを起動したりしないため、多くの場合、これは代替手段よりも高速です。