2013-07-08 22 views
9

tôi là tạo ra một tuyên bố chọn kết hợp hai bảng, zoneoutput, dựa trên một tham chiếu device bảng và trên một ánh xạ zone_number đến output_type_id. Ánh xạ của zone_number đến output_type_id không xuất hiện ở bất kỳ nơi nào trong cơ sở dữ liệu và tôi muốn tạo "trực tiếp" trong câu chọn chọn . Dưới đây là sơ đồ của tôi:Làm thế nào để tạo ra một "on-the-fly" bảng vẽ bản đồ trong một câu lệnh SELECT trong 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) 
); 

Và đây là một số ví dụ dữ liệu:

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

tôi cần để có được những liên enabled lĩnh vực từ bảng đầu ra cho từng khu vực cho một thiết bị nhất định. Mỗi zone_number bản đồ vào một output_type_id. Ví dụ này:

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

Một cách để xử lý các bản đồ sẽ được tạo ra một bảng mới

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

Và sử dụng SQL sau để có được tất cả các khu, cộng với enabled cờ, cho điện thoại 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 

Tuy nhiên, tôi đang tìm kiếm một cách để tạo ra các bản đồ của nunbers khu để đầu ra loại mà không cần tạo một bảng mới và không vẽ ra một bó của A Câu lệnh ND/OR . Có cách nào thanh lịch để tạo ánh xạ giữa hai trường trong câu lệnh chọn không? Một cái gì đó như:

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 

Disclaimer: Tôi biết rằng lý tưởng lĩnh vực enabled sẽ tồn tại trong bảng zone . Tuy nhiên, tôi không có quyền kiểm soát mảnh đó. Tôi chỉ đang tìm kiếm giải pháp thanh lịch nhất từ ​​phía ứng dụng . Cảm ơn!

+0

Có thể bạn có thể sử dụng VIEW? –

+0

Tôi sẽ ổn với điều đó, nhưng ánh xạ bên dưới vẫn cần phải được xác định trong một câu lệnh chọn (trong khung nhìn), và đó là nơi nó phân chia cho tôi. Dường như có một cách đơn giản để tạo khóa/giá trị "băm" có thể được sử dụng trong một câu lệnh chọn để tham gia hai bảng. – Divey

+0

Dữ liệu mẫu 'output_type' của bạn không khớp với đầu ra' của bạn. output_type_id', lần đầu tiên sử dụng 101, 102, 103 và 104 trong khi lần đầu tiên sử dụng 101, 202, 303 và 404; hooray cho FKs cho chỉ ra rằng với tôi :) –

Trả lời

24

Bạn có thể sử dụng VALUES như một bảng nội tuyến và ghép với nó, bạn chỉ cần cung cấp cho nó một bí danh và tên cột:

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

Từ fine manual:

VALUES cũng có thể được sử dụng ở nơi có thể ghi phụ SELECT, cho ví dụ trong mệnh đề 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; 
+0

Hoàn hảo! Điều đó phù hợp với dự luật. – Divey

+2

Đẹp! Bạn thậm chí có thể xác định bí danh cho các cột trong tập hợp kết quả! –

-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

Vì vậy, chỉ để bổ sung cho câu trả lời được chấp nhận, các mã sau đây là một khép kín biểu PostgreSQL hợp lệ mà sẽ đánh giá một 'inline' mối quan hệ với các cột (zone_number, output_type_id):

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

(Chỉ riêng phần (VALUES ... AS ...) sẽ không có biểu thức hợp lệ, đó là lý do tôi thêm SELECT * FROM.)

Các vấn đề liên quan