web-dev-qa-db-ja.com

クエリの複合外部/主キーの列でテーブルを結合する

_CREATE TABLE subscription (
   magazine_id bigint,
   user_id     bigint,
   PRIMARY KEY (magazine_id, user_id)
);

CREATE TABLE delivery (
   magazine_id bigint,
   user_id     bigint,
   FOREIGN KEY (subscription) REFERENCES subscription (magazine_id, user_id)
);
_

特定のサブスクリプションが指定されている場合に配信を照会するための良い方法は何ですか?列名をPRIMARY KEY (magazine_id, user_id)および対応する外部キーに割り当てて、次のようにクエリできるようにする方法はありますか。

_SELECT *
FROM subscription
JOIN delivery ON (delivery.subscription_fk = delivery.subscription_pk);
_

注:次のように書くことができます。

_SELECT *
FROM subscription
JOIN delivery ON (delivery.magazine_id = subscription.magazine_id
              AND delivery.user_id = subscription.user_id);
_

しかし、私はこれを達成するためのより簡潔な方法があるという印象を受けています。

21
samol

NATURAL JOIN

SELECT *
FROM   subscription
NATURAL JOIN delivery;

引用 SELECTのマニュアル

NATURAL

NATURALは、同じ名前を持つ2つのテーブルのすべての列を示すUSINGリストの省略形です。

それはあなたのテスト設定で機能しますが、あなたが求めていることを厳密に実行していません。接続は、同じ名前を共有するすべての列に基づいています。外部キーは考慮されません。 NATURAL JOINは少数であり、はるかに優れたアイデアです。

コードを簡素化/冗長を減らす

手始めに、テーブルエイリアスを使用できます。ONとの結合条件を括弧で囲む必要はありません(USINGとは異なります)。

SELECT *
FROM   subscription s
JOIN   delivery     d ON d.magazine_id = s.magazine_id
                     AND d.user_id = s.user_id;

結合条件の列名は同じであるため、USINGを使用するとさらに簡略化できます。

SELECT *
FROM   subscription s
JOIN   delivery     d USING (magazine_id, user_id);

外部キー制約に基づいて結合を自動的に行う構文バリアントはありません。システムカタログをクエリして、SQLを動的に構築する必要があります。

29

deliveryには、外部キーを表す2つの列がないのですか?次に、非複合主キーSELECT * FROM subscription JOIN delivery ON (delivery.magazine_id = subscription.magazine_id AND delivery.user_id = subscription.user_id)と同じように機能します。

1
Smutje