2011-08-17 173 views
1

設計: 一個主表,其中的每個條目可以包含零個或多個「已選中」選項集。在我看來,如果這些選項是獨立表的一部分並且在主表和選項表之間進行了映射,那麼維護(添加/刪除選項)會更容易。在視圖列中包含一組行

目標: 包含來自主表的信息以及該行已被映射到的所有選項的視圖。然而後一種信息存在於視圖中,應該可以很容易地提取選項的ID和描述。

下面的實現特定於PostgreSQL,但任何跨數據庫的範例都是有意義的。

select語句,做我想做的是:

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語句的視圖生成錯誤: 欄「選項」有僞類型[]

我找到的解決方案是將選項數組(記錄[])轉換爲文本數組(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); 

回答

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)