【问题标题】:Including a set of rows in a view column在视图列中包含一组行
【发布时间】: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


    【解决方案1】:

    您可以创建复合类型,例如temp_options_type 与:

    DROP TYPE IF EXISTS temp_options_type;
    CREATE TYPE temp_options_type AS (id integer, description text);
    

    之后只需将temp_options 转换为array_agg 中的该类型,因此它返回temp_options_type[] 而不是record[]

    DROP VIEW IF EXISTS tstng.vsolution;
    CREATE OR REPLACE VIEW tstng.vsolution AS
        WITH tmp AS
        (
            SELECT
                tmap.MainID AS MainID,
                array_agg(CAST(temp_options AS temp_options_type)) AS options
            FROM
                tstng.tmap INNER JOIN
                (
                    SELECT id, description
                    FROM tstng.toptions
                    ORDER BY description
                ) 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;
    

    示例结果:

    TABLE tstng.vsolution;
     id | contentcolumns |        options        
    ----+----------------+-----------------------
      1 | aaa            | {"(1,xxx)","(2,yyy)"}
      2 | bbb            | {"(3,zzz)"}
      3 | ccc            | {"(1,xxx)"}
    (3 rows)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-02
      • 1970-01-01
      • 1970-01-01
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多