Postgresql选择具有行的特定值的所有列和列名称

时间:2014-03-02 16:59:09

标签: postgresql

我有一个包含许多(+1000)列和行(~1M)的表。列的值为1,或者为NULL。

我希望能够为特定行(用户)选择检索值为1的列名。

由于表上有许多列,因此指定列将产生极长的查询。

1 个答案:

答案 0 :(得分:0)

你正在做一些非常糟糕的事情 - 动态访问列,或将行视为一组。如果这更容易,那将是很好的,但它不适用于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);

我会使用hstore(或者在较新的PostgreSQL版本中,json函数)将每一行转换为键/值集。 SQL本身无法动态访问列,因此我们必须使用扩展。所以:

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

然后将hstore提取到集合:

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)