【发布时间】:2023-03-21 02:52:01
【问题描述】:
设计: 一个主表,其中的每个条目都可以有零个或多个“选中”的一组选项。在我看来,如果选项是单独表的一部分并且在主表和选项表之间进行映射,则维护(添加/删除选项)会更容易。
目标: 包含来自主表的信息以及该行已映射到的所有选项的视图。然而后一个信息存在于视图中,应该可以很容易地提取选项的 ID 及其描述。
下面的实现是特定于 PostgreSQL 的,但是任何跨数据库工作的范式都是有意义的。
执行我想要的选择语句是:
WITH tmp AS (
SELECT
tmap.MainID AS MainID,
array_agg(temp_options) AS options
FROM tstng.tmap
INNER JOIN (SELECT id, description FROM tstng.toptions ORDER BY description ASC) AS temp_options
ON tmap.OptionID = temp_options.id
GROUP BY tmap.MainID
)
SELECT tmain.id, tmain.contentcolumns, tmp.options
FROM tstng.tmain
INNER JOIN tmp
ON tmain.id = tmp.MainID;
但是,尝试从此 select 语句创建视图会产生错误: “选项”列具有伪类型记录[]
我找到的解决方案是将选项数组 (record[]) 转换为文本数组 (text[][]);但是,我很想知道是否有更好的解决方案。 供参考,创建指令:
CREATE OR REPLACE VIEW tstng.vsolution AS
WITH tmp AS (
SELECT
tmap.MainID AS MainID,
array_agg(temp_options) AS options
FROM tstng.tmap
INNER JOIN (SELECT id, description FROM tstng.toptions ORDER BY description ASC) AS temp_options
ON tmap.OptionID = temp_options.id
GROUP BY tmap.MainID
)
SELECT tmain.id, tmain.contentcolumns, CAST(tmp.options AS text[][])
FROM tstng.tmain
INNER JOIN tmp
ON tmain.id = tmp.MainID;
最后,DDL 以防我的描述不清楚:
CREATE TABLE tstng.tmap (
mainid INTEGER NOT NULL,
optionid INTEGER NOT NULL
);
CREATE TABLE tstng.toptions (
id INTEGER NOT NULL,
description text NOT NULL,
unwanted_column text
);
CREATE TABLE tstng.tmain (
id INTEGER NOT NULL,
contentcolumns text
);
ALTER TABLE tstng.tmain ADD CONSTRAINT main_pkey PRIMARY KEY (id);
ALTER TABLE tstng.toptions ADD CONSTRAINT toptions_pkey PRIMARY KEY (id);
ALTER TABLE tstng.tmap ADD CONSTRAINT tmap_pkey PRIMARY KEY (mainid, optionid);
ALTER TABLE tstng.tmap ADD CONSTRAINT tmap_optionid_fkey FOREIGN KEY (optionid)
REFERENCES tstng.toptions (id);
ALTER TABLE tstng.tmap ADD CONSTRAINT tmap_mainid_fkey FOREIGN KEY (mainid)
REFERENCES tstng.tmain (id);
【问题讨论】:
标签: sql postgresql view common-table-expression