2014-03-02 156 views
0

我有一個包含許多(+1000)列和行(〜1M)的表。列的值爲1,或者爲NULL。Postgresql爲一行選擇具有特定值的所有列和列名稱

我希望能夠選擇,對於一個特定行(用戶)檢索具有的1

由於有上表中的許多列值的列名,指定列將產生一個非常長查詢。

+0

你可以行轉換爲'hstore'對象,然後將其轉換爲單獨的鍵和值數組,並只返回值爲1的鍵。 –

+0

爲什麼這很奇怪?轉換爲稀疏矩陣時,我的表格非常寬以節省空間。 –

+0

@ManuelG這個目標很有意義,但是SQL在動態列訪問方面非常糟糕。所以你節省了空間,並且交換了一個很難解決的問題。要處理這些行,你基本上必須將它們轉化爲鍵/值形式。 –

回答

0

您正在做的事情SQL在動態訪問列或將一行視爲集合時很糟糕。如果這更容易,它會很好,但它不適用於SQL的鍵入本質和關係的概念。以目前的形式處理您的數據集將會令人沮喪;考慮存儲一個數組,jsonhstore的值。

實際上,對於這個特定的數據模型,你可能可以使用一個位域。見bit(n) and bit varying(n)

儘管仍然可以使用當前的PostgreSQL擴展模塊進行工作查詢。

鑑於樣品:

CREATE TABLE blah (id serial primary key, a integer, b integer, c integer); 
INSERT INTO blah(a,b,c) VALUES (NULL, NULL, 1), (1, NULL, 1), (NULL, NULL, NULL), (1, 1, 1); 

我UNPIVOT每一行到使用hstore(或在新的PostgreSQL版本中,JSON功能)鍵/值集合。 SQL自身沒有辦法動態訪問列,所以我們必須使用擴展。所以:

SELECT id, hs FROM blah, LATERAL hstore(blah) hs; 

然後提取hstore s到集:

SELECT id, k, v FROM blah, LATERAL each(hstore(blah)) kv(k,v); 

...此時您可以篩選符合標準值。請注意,所有列已轉換爲text,所以你可能想將它轉換回:

SELECT id, k FROM blah, LATERAL each(hstore(blah)) kv(k,v) WHERE v::integer = 1; 

您還需要從配套排除id,所以:

regress=> SELECT id, k FROM blah, LATERAL each(hstore(blah)) kv(k,v) WHERE v::integer = 1 AND 
k <> 'id'; 
id | k 
----+--- 
    1 | c 
    2 | a 
    2 | c 
    4 | a 
    4 | b 
    4 | c 
(6 rows) 
相關問題