我有一个包含数百万行的大表:
CREATE TABLE mytable (
row_id bigint,
col_id bigint,
value double precision,
timestamp timestamp
);
假设:
list_row
= row_id
的列表(如果需要,可以订购)list_col
= col_id
的列表(如果需要,可再次订购)我如何(有效地)返回资源:
col_id
中出现的所有list_col
,其出现方式与col_id
中list_col
出现的顺序相同
row_id
中存在的所有list_row
(它们不需要以相同的顺序出现)value
和row_id
的{{1}}个。col_id
对的value
感兴趣,即使用row_id:col_id
)或类似的过滤器MAX(timestamp
坐标没有记录value
,则该字段应为row_id:col_id
。一个澄清的视觉例子。初始表:
null
变为:
+--------+--------+-------+-----------+
| row_id | col_id | value | timestamp |
+========+========+=======+===========+
| 10 | 20 | 100 | 2016-0... |
| 10 | 21 | 200 | 2015-0... |
| 11 | 20 | 300 | 2016-1... |
| 11 | 22 | 400 | 2016-0... |
+--------+--------+-------+-----------+
我怀疑正确的答案是首先创建一个目标为 col_id →
+-----------------+
| 20 | 21 | 22 |
+=====+=====+=====+
row_id (10) | 100 | 200 | |
↓ (11) | 300 | | 400 |
+-----+-----+-----+
的临时表作为列,然后进行某种连接。我无法弄清楚如何有效地做到这一点。是否可以在不需要每个col_id
的临时表的情况下执行此操作?
答案 0 :(得分:1)
crosstab()
适用于常规查询:
但不因为:
- 两个列表可能都非常大(可能是数十万)
醇>
Postgres的专栏太多了。 The manual:
表格可以包含的列数限制。取决于 列类型,介于 250和1600 之间。但是,定义一个 在这么多列附近的任何地方的桌子都非常不寻常并经常 一个有问题的设计。
我建议改为返回数组。像(适用于任何现代Postgres版本):
SELECT row_id
, array_agg(col_id) AS cols
, array_agg(value) AS vals
FROM (
SELECT DISTINCT ON (row_id, col_id) -- most recent values for row_id:col_id pair
row_id, col_id, value
FROM mytable
WHERE row_id IN (<long list>)
AND col_id IN (<long list>)
ORDER BY row_id, col_id, timestamp DESC
) sub
GROUP BY 1;
关于DISTINCT ON
:
返回数据的几种替代方法:
SELECT json_agg(json_build_object('col_id', col_id
, 'value' , value)) AS col_values1 -- requires pg 9.4+
, json_agg(json_build_object(col_id, value)) AS col_values2 -- requires pg 9.4+
, array_agg(ARRAY[col_id, value]) AS col_values3 -- requires pg 9.5+
, array_agg(hstore(col_id::text, value::text)) AS col_values4 -- requires pg 8.3+
FROM ... -- same as above
最后一个需要额外的模块hstore
。