2012-07-13 34 views
3

我工作的PostgreSQL 9.1創建表,我有以下表格:與動態列

element(element_id int, name varchar, category_id int) 

category(category_id int, name varchar) 

characteristic(characteristic_id int, name varchar, unit varchar) 

category_characteristic(characteristic_id, category_id) 

element_characteristic(element_id, characteristic_id, value) 

試想下表:

elements 
--------------------- 
|id|name |category | 
----------------------- 
|1 |'item 1'|1  | 
|2 |'item 2'|2  | 
|3 |'item 3'|1  | 
--------------------- 

category 
---------------- 
|id|name   | 
|----------------| 
|1 | 'category 1'| 
|2 | 'category 2'| 
---------------- 

characteristic 
-------------------------------- 
|id|name    |unit  | 
-------------------------------- 
|1 |'characteristic 1' | 'unit 1'| 
|2 |'characteristic 2' | 'unit 2'| 
|3 |'characteristic 3' | 'unit 3'| 
|4 |'characteristic 4' | 'unit 4'| 
|5 |'characteristic 5' | 'unit 5'| 
|6 |'characteristic 6' | 'unit 6'| 
-------------------------------- 

category_characteristic 
------------------------------ 
|category_id|characteristic_id | 
|------------------------------ 
|1   |1     | 
|1   |2     | 
|1   |4     | 
|1   |5     | 
|2   |1     | 
|2   |3     | 
|2   |5     | 
------------------------------ 

element_characteristic 
--------------------------------------- 
|id_element|id_characteristic|value  | 
|---------------------------------------| 
|1   |1    |'value a' | 
|1   |2    |'value b' | 
|1   |4    |'value c' | 
|1   |5    |'value d' | 
|2   |1    |'value e' | 
|2   |3    |'value f' | 
|2   |5    |'value g' | 
|3   |1    |'value h' | 
|3   |2    |'value i' | 
|3   |4    |'value j' | 
|3   |5    |'value k' | 
--------------------------------------- 

現在我想以下表格:

category 1 
--------------------------------------------------------------------------- 
|name |characteristic 1|characteristic 2|characteristic 4|characteristic 5| 
| --------------------------------------------------------------------------| 
|item 1 |value a   |value b   |value c   |value d   | 
|item 3 |value h   |value i   |value j   |value k   | 
--------------------------------------------------------------------------- 

category 2 
----------------------------------------------------------- 
|name |characteristic 1|characteristic 3|characteristic 5| 
| ---------------------------------------------------------- 
|item 2 |value e   |value f   |value g   | 
---------------------------------------------------------- 

我想了解什麼是b預測程序走低谷。我已經閱讀了tablefunc文檔,但我無法弄清楚如何動態創建這些過程,因爲類別表中會有N個條目。某種方向將非常感激。

+0

+1恰好格式化完整的問題。 – 2012-07-13 20:44:02

+0

被警告:這是一個「實體屬性值」模型。這些可能在一開始就是強大的玩具,最終會導致性能不佳。查找谷歌的「評論」。您也可以查找hstore來獲取PostgreSQL特有的更高性能的解決方案。 – 2012-07-15 09:56:10

+0

就我而言,我認爲這是正確的路要走。我正在管理100到1000個元素,性能似乎不是這類數字的問題......除此之外,我真的需要這種類型的結構,因爲我稍後需要它來執行計算。感謝您的建議! – NewK 2012-07-15 21:27:25

回答

3

解決方案:

SELECT * 
FROM crosstab (
     'SELECT e.name, c.name, ec.value 
     FROM elements e 
     JOIN element_characteristic ec ON ec.id_element = e.id 
     JOIN characteristic c ON c.id = ec.id_characteristic 
     ORDER BY 1, 2', 

     'SELECT DISTINCT name 
     FROM characteristic 
     ORDER BY 1') 
AS tbl (
    name text 
,characteristic_1 text 
,characteristic_2 text 
,characteristic_3 text 
,characteristic_4 text 
,characteristic_5 text 
,characteristic_6 text 
); 

測試設置:

CREATE TEMP TABLE elements(id int, name text, category int); 
INSERT INTO elements VALUES 
(1, 'item 1', 1) 
,(2, 'item 2', 2) 
,(3, 'item 3', 1); 

CREATE TEMP TABLE element_characteristic(id_element int 
             ,id_characteristic int, value text); 
INSERT INTO element_characteristic VALUES 
(1,1,'value a') 
,(1,2,'value b') 
,(1,4,'value c') 
,(1,5,'value d') 
,(2,1,'value e') 
,(2,3,'value f') 
,(2,5,'value g') 
,(3,1,'value h') 
,(3,2,'value i') 
,(3,4,'value j') 
,(3,5,'value k'); 

CREATE TEMP TABLE characteristic (id int, name text, unit text); 
INSERT INTO characteristic VALUES 
(1,'characteristic 1', 'unit 1') 
,(2,'characteristic 2', 'unit 2') 
,(3,'characteristic 3', 'unit 3') 
,(4,'characteristic 4', 'unit 4') 
,(5,'characteristic 5', 'unit 5') 
,(6,'characteristic 6', 'unit 6'); 

結果:

name | characteristic 1 | characteristic_2 | characteristic_3 | characteristic_4 | characteristic_5 | characteristic_6 
-------|------------------|------------------|------------------|------------------|------------------|---------------- 
item 1 | value a   | value b   | <NULL>   | value c   | value d   | <NULL> 
item 2 | value e   | <NULL>   | value f   | <NULL>   | value g   | <NULL> 
item 3 | value h   | value i   | <NULL>   | value j   | value k   | <NULL> 

你的問題的解決方案是使用crosstab()變異與兩個參數

查詢輸出所有項目。將第一個查詢添加WHERE子句以篩選類別。

第二個參數(另一查詢字符串)產生輸出列的列表中,使得在數據查詢NULL值(第一個參數)被正確地分配。

檢查的手冊tablefunc extension,特別crosstab(text, text)

我已經發布關於tablefunc模塊的crosstab()功能一對夫婦的答案。 This search會給你更多的例子和解釋。

+0

非常感謝。這很好!只有一個問題,這個例子我只有6個特徵,如果我有一個未知數的特徵(假設有100個特徵,每個特徵的平均特徵爲4〜7個特徵)呢?創建一個過程來完成具有多個特徵的查詢是正確的方法嗎?再一次,非常感謝你,我會閱讀你的functab相關文章。 – NewK 2012-07-15 21:19:36

+0

@NewK:很好用!至於具有100多個特徵的情況,這是一個不同的問題。我建議你**開一個新的**,在那裏你準確地定義你想要的東西。所有100個特徵在不同的行中?數據中有10行有列名?按特徵數量排序?如果您不想重新發布相同的數據模型,則始終可以引用此問題。 – 2012-07-15 22:21:37