2013-07-08 9 views
9

私が参照deviceテーブルの上とのマッピングに基づいて、2つのテーブル、zoneoutput、 を組み合わせたselect文を作成していますで、SELECT文の中に「オンザフライ」マッピングテーブルを作成する方法zone_numberoutput_type_idzone_numberからoutput_type_idへのマッピングは、 データベース内のどこにも表示されず、選択した ステートメント内で「オンザフライ」で作成したいと考えています。以下は私のスキーマです:Postgresqlの

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_numberoutput_type_idにマッピングされます。この例:

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

マッピングが

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); 

を新しいテーブルを作成し、デバイス1のために、すべてのゾーンに加え、enabledフラグを取得するには、次のSQLを使用することであろう処理する1つの方法:

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 

しかし、私は 種類の新しいテーブルを作成せずに、一緒にAの束を縫い合わせずに出力へのゾーンnunbersのマッピングを作成する方法を探していますND/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 テーブルに存在することを知っています。しかし、私はその作品を支配していません。私はちょうどアプリケーション側から 最も洗練されたソリューションを探しています。ありがとう!

+0

VIEWを使用できますか? –

+0

これで問題はありませんが、基本的なマッピングは(ビュー内の)selectステートメント内で定義する必要があり、それが私のために分解されます。 2つのテーブルを結合するためにselectステートメント内で使用できるキー/値 "ハッシュ"を作成する簡単な方法があるはずです。 – Divey

+0

あなたの 'output_type'サンプルデータがあなたの'出力と一致しません。第1のものは101,102,103,104を使用し、第2のものは101,202,303,404を使用する。私にそれを指摘するためのFKのためのhooray :) –

答えて

24

あなたはちょうどそれをエイリアスとカラム名を与える必要があり、インラインテーブルとしてVALUESを使用して、それに参加することができます:fine manualから

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

VALUES の例では、FROM句の中にサブSELECTが書かれている場合には、

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; 
+0

パーフェクト!それは法案に合っている。 – Divey

+2

美しい!結果セットの列のエイリアスを定義することもできます。 –

-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 
0

だから受け入れ答えを補完するために、次のコードは、列(zone_number, output_type_id)と「インライン」関係に評価する有効な、自己完結型 PostgreSQLの式である:

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

(部分のみでは有効な表現ができません。そのため、SELECT * FROMを追加しました)