17

参照されるテーブルとへのマッピングに基づいて、zoneとの2 つのテーブルを結合する select ステートメントを作成しています。toのマッピングはデータベースのどこにも表示されず、select ステートメント内で「オンザフライ」で作成したいと考えています。以下は私のスキーマです:outputdevicezone_numberoutput_type_idzone_numberoutput_type_id

CREATE TABLE output_type (
    id INTEGER NOT NULL, 
    name TEXT,
    PRIMARY KEY (id)
);

CREATE TABLE device (
    id INTEGER NOT NULL,
    name TEXT,
    PRIMARY KEY (id)
);

CREATE TABLE zone (
    id SERIAL NOT NULL,
    device_id INTEGER NOT NULL REFERENCES device(id),
    zone_number INTEGER NOT NULL,
    PRIMARY KEY (id), 
    UNIQUE (zone_number)
);

CREATE TABLE output (
    id SERIAL NOT NULL,
    device_id INTEGER NOT NULL REFERENCES device(id),
    output_type_id INTEGER NOT NULL REFERENCES output_type(id),
    enabled BOOLEAN NOT NULL,
    PRIMARY KEY (id)
);

そして、ここにいくつかのサンプルデータがあります:

INSERT INTO output_type (id, name) VALUES 
(101, 'Output 1'),
(202, 'Output 2'),
(303, 'Output 3'),
(404, 'Output 4');

INSERT INTO device (id, name) VALUES 
(1, 'Test Device');

INSERT INTO zone (device_id, zone_number) VALUES 
(1, 1),
(1, 2),
(1, 3),
(1, 4);

INSERT INTO output (device_id, output_type_id, enabled) VALUES 
(1, 101, TRUE),
(1, 202, FALSE),
(1, 303, FALSE), 
(1, 404, TRUE);

enabled特定のデバイスの各ゾーンの出力テーブルから関連するフィールドを取得する必要があります。それぞれzone_numberが にマップされますoutput_type_id。この例では:

zone_number | output_type_id
----------------------------
1           | 101
2           | 202
3           | 303 
4           | 404

マッピングを処理する 1 つの方法は、新しいテーブルを作成することです。

CREATE TABLE zone_output_type_map (
    zone_number INTEGER,
    output_type_id INTEGER NOT NULL REFERENCES output_type(id)
);

INSERT INTO zone_output_type_map (zone_number, output_type_id) VALUES 
(1, 101),
(2, 202),
(3, 303), 
(4, 404);

次の SQL を使用して、デバイス 1 のすべてのゾーンとenabledフラグを取得します。

SELECT zone.*, output.enabled 
FROM zone
JOIN output 
ON output.device_id = zone.device_id
JOIN zone_output_type_map map
ON map.zone_number = zone.zone_number
AND map.output_type_id = output.output_type_id
AND zone.device_id = 1

ただし、新しいテーブルを作成したり、AND/OR ステートメントをつなぎ合わせたりせずに、ゾーン番号から出力タイプへのマッピングを作成する方法を探しています。selectステートメント内の2つのフィールド間のマッピングを作成するエレガントな方法はありますか? 何かのようなもの:

SELECT zone.*, output.enabled 
FROM zone
JOIN output 
ON output.device_id = zone.device_id
JOIN (
    SELECT (
        1 => 101,
        2 => 202,
        3 => 303,
        4 => 404
    ) (zone_number, output_type_id)
) as map
ON map.zone_number = zone.zone_number
AND map.output_type_id = output.output_type_id
AND zone.device_id = 1

enabled免責事項: 理想的には、フィールドがテーブルに存在することを知っていzone ます。しかし、私はその部分を制御できません。アプリケーション側から最もエレガントなソリューションを探しています。ありがとう!

4

3 に答える 3

41

インライン テーブルとして使用VALUESし、それに JOIN することができます。エイリアスと列名を指定するだけで済みます。

join (values (1, 101), (2, 202), (3, 303), (4, 304)) as map(zone_number, output_type_id)
on ...

細かいマニュアルから:

VALUESsub-SELECTが書かれている可能性がある場所、たとえばFROM節で使用することもできます。

SELECT f.*
  FROM films f, (VALUES('MGM', 'Horror'), ('UA', 'Sci-Fi')) AS t (studio, kind)
  WHERE f.studio = t.studio AND f.kind = t.kind;

UPDATE employees SET salary = salary * v.increase
  FROM (VALUES(1, 200000, 1.2), (2, 400000, 1.4)) AS v (depno, target, increase)
  WHERE employees.depno = v.depno AND employees.sales >= v.target;
于 2013-07-08T18:08:23.653 に答える
7

したがって、受け入れられた回答を補完するために、次のコードは、列との「インライン」関係に評価される有効な自己完結型の(zone_number, output_type_id)Postgresql 式です。

SELECT * FROM 
(VALUES 
  (1, 101), 
  (2, 202), 
  (3, 303), 
  (4, 304)
) as i(zone_number, output_type_id)

(この(VALUES ... AS ...)部分だけでは有効な表現にならないので、 を追加しましたSELECT * FROM。)

于 2017-08-10T16:55:01.900 に答える
-1
JOIN 
(SELECT 1 zone_number, 101 as output_type_id
 UNION ALL
 SELECT 2 zone_number, 202 as output_type_id
 UNION ALL
 SELECT 3 zone_number, 303 as output_type_id
) mappings on mappings.zone_number = zone.zone_number
于 2013-07-08T17:32:11.713 に答える