PostgreSQL で、SQL ステートメントを使用して 2 つの列を結合し、それらから新しい列を作成したいと考えています。
を使おうと思っているのですconcat(...)
が、何か良い方法はありませんか?
これを行う最善の方法は何ですか?
PostgreSQL で、SQL ステートメントを使用して 2 つの列を結合し、それらから新しい列を作成したいと考えています。
を使おうと思っているのですconcat(...)
が、何か良い方法はありませんか?
これを行う最善の方法は何ですか?
一般的に、@kgrittn のアドバイスに同意します。頑張れ。
しかし、あなたの基本的な質問に対処するにはconcat()
: 新しい関数は、 null 値concat()
を処理する必要がある場合に役立ちます。null は、質問でも参照する質問でも除外されていません。
null 値を除外できる場合||
でも、古き良き (SQL 標準) 連結演算子が最良の選択であり、@luis の答えは問題ありません。
SELECT col_a || col_b;
いずれかの列が null になる可能性がある場合、その場合、結果は null になります。あなたはで守ることができますCOALESCE
:
SELECT COALESCE(col_a, '') || COALESCE(col_b, '');
しかし、それは引数が増えるとすぐに退屈になります。これは、すべての引数が nullであっても、null を返すことconcat()
はありません。ドキュメントごと:
NULL 引数は無視されます。
SELECT concat(col_a, col_b);
両方の選択肢の残りのコーナー ケースは、すべての入力列が nullであり、その場合でも空の string を取得します''
が、代わりに 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)
です。また、すべての列が nullの場合にのみ、行の型がnull になります。詳細な説明:
また、concat_ws()
要素間にセパレーターを追加するために使用します ( ws
「セパレーター付き」の場合)。
ケビンの答えのような表現:
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 | ナニュエット | ニューヨーク | +---------+--------+-------+
ここで、テーブルのレコード タイプを唯一のパラメーターとして受け取る目的の「列名」を持つ関数を追加します。
CREATE FUNCTION combined(rec tbl)
RETURNS text
LANGUAGE SQL
AS $$
SELECT $1.zipcode || ' - ' || $1.city || ', ' || $1.state;
$$;
これにより、次のように、テーブル名またはエイリアスが指定されている限り、テーブルの列であるかのように使用できる関数が作成されます。
SELECT *, tbl.combined FROM tbl;
次のように表示されます。
+--------+--------+-------+--------------------+ | | 郵便番号 | 都市 | 状態 | 結合 | +--------+--------+-------+--------------------+ | | 10954 | ナニュエット | ニューヨーク | 10954 - ニューヨーク州ナニュエット | +--------+--------+-------+--------------------+
これが機能するのは、PostgreSQL が最初に実際の列をチェックするためですが、列が見つからず、識別子がリレーション名またはエイリアスで修飾されている場合、上記のような関数を探し、行を引数として実行し、戻り値を返します。列であるかのような結果。必要に応じて、そのような「生成された列」にインデックスを付けることもできます。
複製されたデータのために各行で余分なスペースを使用したり、すべての挿入と更新でトリガーを起動したりしないため、多くの場合、これは代替方法よりも高速になります。