我有一个包含许多(+1000)列和行(~1M)的表。列的值为1,或者为NULL。
我希望能够为特定行(用户)选择检索值为1的列名。
由于表上有许多列,因此指定列将产生极长的查询。
答案 0 :(得分:0)
你正在做一些非常糟糕的事情 - 动态访问列,或将行视为一组。如果这更容易,那将是很好的,但它不适用于SQL的类型性质和关系的概念。以当前形式处理您的数据集将会令人沮丧;考虑存储数组,json
或hstore
值。
实际上,对于这个特定的数据模型,您可能使用位域。请参阅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)