我创建了一个结合了两个表zone
和output
的select语句,
基于引用的device
表以及zone_number
到output_type_id
的映射。
zone_number
到output_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
处理映射的一种方法是创建一个新表
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
但是,我正在寻找一种方法来创建区域nunbers到输出的映射 类型没有创建一个新表,也没有拼凑一堆AND / OR 声明。是否有一种优雅的方法来创建两个字段之间的映射 在select语句中?类似的东西:
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 :(得分:30)
您可以使用VALUES
作为内联表并加入它,您只需要为其指定别名和列名称:
join (values (1, 101), (2, 202), (3, 303), (4, 304)) as map(zone_number, output_type_id)
on ...
来自fine manual:
VALUES
也适用于可能为其编写子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;
答案 1 :(得分:3)
因此,为了补充已接受的答案,以下代码是一个有效的,自包含 Postgresql表达式,它将评估为与列(zone_number, output_type_id)
的“内联”关系:
SELECT * FROM
(VALUES
(1, 101),
(2, 202),
(3, 303),
(4, 304)
) as i(zone_number, output_type_id)
(仅(VALUES ... AS ...)
部分不会生成有效的表达式,这就是我添加SELECT * FROM
的原因。)
答案 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