2017-05-09 63 views
1

問題

我有一個PostgreSQL 9.6數據庫,根據不同類型的值的EAV模型設計了一個表格。的示例摘錄看起來像這樣:PostgreSQL的交叉與動態列名和多輸入列

name |arrivalTime | boolValue | intValue | floatValue | stringValue 
------+------------+-----------+----------+------------+------------ 
a1 | 10:00:00 | true |   |   | 
c3 | 10:00:00 |   | 12  |   | 
d4 | 10:00:00 |   |   |   | hello 
e5 | 15:00:00 |   |   | 45.67 | 
c3 | 15:00:00 |   | 45  |   | 
b2 | 20:00:00 |   |   | 4.567 | 
a1 | 20:00:00 | false |   |   | 
d4 | 22:00:00 |   |   |   | bye 
b2 | 22:00:00 |   |   | 12.34 | 

空單元表示在數據庫中null值。

現在我想要得到一個數據透視表,新列是arrivalTime,內容是name。對於示例從上面應該是這樣的:

arrivalTime | a1 | b2 | c3 | d4 | e5 
------------+-------+-------+-------+-------+------- 
    10:00:00 | true |  | 12 | hello | 
    15:00:00 |  |  | 45 |  | 45.67 
    20:00:00 | false | 4.567 |  |  | 
    22:00:00 |  | 12.34 |  | bye | 

作爲輸入來查詢用於檢索這個結果我得到一個圖案匹配name S和開始和結束時間指定的arrivalTime的範圍內。原始表的

屬性:

  • 在名稱列中的條目是揮發性的,即新的名字進來 老名字經常消失。
  • namearrivalTime的每種組合都是獨特的。
  • 每個namearrivalTime組合在其中一個值列中只有一個條目。

想法

我已經給了它一些注意事項:

示例表

這裏是SQL代碼來創建實例表:

CREATE TABLE IF NOT EXISTS playTable (
    name TEXT NOT NULL, 
    arrivalTime TIME NOT NULL, 
    floatValue REAL NULL, 
    intValue INT NULL, 
    boolValue BOOLEAN NULL, 
    stringValue TEXT NULL, 
    PRIMARY KEY (name, arrivalTime), 
    CONSTRAINT single_value CHECK(
    (boolValue IS NOT NULL)::INT + 
    (intValue IS NOT NULL)::INT + 
    (floatValue IS NOT NULL)::INT + 
    (stringValue IS NOT NULL)::INT = 1 
) 
); 

並插入的值:

INSERT INTO playTable (name, arrivalTime, boolValue) VALUES ('a1', '10:00:00', true); 
INSERT INTO playTable (name, arrivalTime, intValue) VALUES ('c3', '10:00:00', 12); 
INSERT INTO playTable (name, arrivalTime, stringValue) VALUES ('d4', '10:00:00', 'hello'); 
INSERT INTO playTable (name, arrivalTime, floatValue) VALUES ('e5', '15:00:00', 45.67); 
INSERT INTO playTable (name, arrivalTime, intValue) VALUES ('c3', '15:00:00', 45); 
INSERT INTO playTable (name, arrivalTime, floatValue) VALUES ('b2', '20:00:00', 4.567); 
INSERT INTO playTable (name, arrivalTime, boolValue) VALUES ('a1', '20:00:00', false); 
INSERT INTO playTable (name, arrivalTime, stringValue) VALUES ('d4', '22:00:00', 'bye'); 
INSERT INTO playTable (name, arrivalTime, floatValue) VALUES ('b2', '22:00:00', 12.34); 

透視表,非動態

klin provid我猜:

SELECT * 
FROM crosstab(
    $ct$ 
     SELECT 
      arrivalTime, name, concat(boolValue, intValue, floatValue, stringValue) 
     FROM playTable 
     ORDER BY 1, 2 
    $ct$, 
    $ct$ 
     SELECT DISTINCT name 
     FROM playTable 
     ORDER BY 1 
    $ct$) 
AS ct("arrivalTime" time, "a1" BOOLEAN, "b2" REAL, "c3" INT, "d4" TEXT, "e5" REAL); 

這個解決方案缺少的是動態方面。作爲輸入,提供nameLIKE模式,並且範圍(即,最小值和最大值)爲arrivalTime。這使得as ct(...)的論點變得動態。

回答

1

使用coalesce()去年四列。你必須列轉換爲text做到這一點:

select * 
from crosstab(
    $ct$ 
     select 
      arrivaltime, name, 
      coalesce(boolvalue::text, intvalue::text, floatvalue::text, stringvalue) 
     from my_table 
     order by 1, 2 
    $ct$, 
    $ct$ 
     select distinct name 
     from my_table 
     order by 1 
    $ct$) 
as ct("arrivalTime" time, "a1" text, "b2" text, "c3" text, "d4" text, "e5" text); 

arrivalTime | a1 | b2 | c3 | d4 | e5 
-------------+-------+-------+----+-------+------- 
10:00:00 | true |  | 12 | hello | 
15:00:00 |  |  | 45 |  | 45.67 
20:00:00 | false | 4.567 | |  | 
22:00:00 |  | 12.34 | | bye | 
(4 rows) 

我用arrivalTime time因爲示例數據的格式,將其更改爲timestamp

+0

我的解決方案發揮各地和擴展我的問題有點。我將'coalesce'改爲'concat'。 能正常工作的重要障礙採取,但我不是在終點尚未: 仍下落不明是把在模式指定'name'和'arrivalTime'範圍的能力。這使「ct(...)」動態的論點成爲可能。 – user711270

+0

user711270您需要任何編程languge的,將生成SQL查詢你的,採取的輸入模式照顧。如果你在SQL中只使用plpgsql來創建這樣的動態查詢。 –