いくつかの列名が共通する2つのテーブルを結合する共通テーブル式があります。
CREATE TABLE first(
id serial PRIMARY KEY,
data VARCHAR,
date DATE
);
CREATE TABLE second(
id serial PRIMARY KEY,
key INT REFERENCES first(id),
data VARCHAR,
date DATE
);
WITH cte AS
(SELECT * FROM first JOIN second ON first.id=second.key)
SELECT data FROM cte;
もちろん、フィールドdata
があいまいであるため、これはエラーになります。
CTEを使用してあいまいな列を抽出し、それらに一意の名前を付けることができることを知っています。
問題は、メインのSELECTステートメントからこのあいまいさを解決できるかどうかです。あるいは、実際に新しい名前を作成せずにこれを不可能にするためにCTE内で使用できる表記法はありますか?
編集
ワイルドカードの使用は適切ではないことを示唆するコメントがいくつかあります。ここでは、クエリを簡略化するためにのみ使用します。深刻なクエリでは使用しません。ここに別のバージョンがあります:
WITH cte AS
(SELECT f.id as fid, s.id as sid, f.data, s.data
FROM first f JOIN second s ON f.id=s.key
)
SELECT data FROM cte;
CTEでエイリアスを付けることで問題を解決できることを知っています。
WITH cte AS
(SELECT f.id as fid, s.id as sid, f.data as fdata, s.data as sdata
FROM first f JOIN second s ON f.id=s.key
)
SELECT fdata FROM cte;
要件に一致する実際のソリューションはありませんが、考慮すべき点がいくつかあります要件について。
まず、誤った名前の列について発生したエラーが生成するヒントを見てみましょう。
WITH ts AS (
SELECT * FROM t1 JOIN t2 USING (t_id)
) SELECT col2 FROM ts;
ERROR: column "col2" does not exist
LINE 1: ...AS (SELECT * FROM t1 JOIN t2 USING (t_id)) SELECT col2 FROM ...
^
HINT: Perhaps you meant to reference the column "ts.col1" or the column "ts.col1".
データベースでさえ、2つのインデントされた名前の列から選択することを提案しています。これは、ご想像のとおり、不可能です。 (興味深いことに、テーブルは言うまでもなく、ビューの定義ではそのようなことはできません。)
したがって、要件について:
通常、最初に*
を使用しないのが賢明です。タイプするのが速くなることは別として、それはあまり多くをもたらしません。メインSELECT
を作成するとき、通常、必要な列がわかります。CTE内に追加するだけです。これは、クエリのパフォーマンス(データセットのサイズを小さく表示するため)にも有益な場合があります。
入力を簡単にしたい場合は、次のようなことを試すことができます
SELECT f.*, s.data AS s_data
FROM first AS f JOIN second AS s ON f.id = s.key
私の慣例では、テーブル名から派生したプレフィックスを使用して列に名前を付けることをお勧めします。
CREATE TABLE first(
f_id serial PRIMARY KEY,
f_data VARCHAR,
f_date DATE
);
CREATE TABLE second(
s_id serial PRIMARY KEY,
s_first_id INT REFERENCES first(id), -- an exception, for making more clear
-- what the column refers to
s_data VARCHAR,
s_date DATE
);
この方法では、大きなデータベースであっても、同じ名前の列を持つことは非常にまれです。そして、これはあなたが戦っている問題を完全に取り除きます。