我有一个像这样的数据表:
CREATE TABLE public.data
(
data_id bigint,
date timestamp without time zone,
value double precision,
sensor_id integer,
version_id integer
)
现在,我需要一个性能良好的查询,该查询可检索每个sensor_id和日期具有最高version_id的所有数据行。
换句话说,这行:
date='2018-08-24 10:31';value=1337;sensor_id=1;version_id=1;
date='2018-08-24 10:31';value=4;sensor_id=1;version_id=2;
date='2018-08-24 10:32';value=45;sensor_id=1;version_id=1;
应将查询引向该结果数据行:
date='2018-08-24 10:31';value=4;sensor_id=1;version_id=2;
date='2018-08-24 10:32';value=45;sensor_id=1;version_id=1;
因此应该忽略所有具有较新版本的行。
问题是,我需要一个非常好的性能,因为数据表可能包含例如2.000.000.000行(它们在背景中进行了分区-与我猜到的问题无关)。
我的问题的简单解决方案是检查子查询中的每一行是否是具有最高version_number的行:
SELECT * FROM data d1
WHERE d1.version_id= (
SELECT MAX(d2.version_id) FROM data d2
WHERE d2.sensor_id = d1.sensor_id AND d2.date = d2.date
);
这非常慢。顺便说一句:该表具有以下唯一索引和b树索引:
CREATE UNIQUE INDEX data_unique_index
ON public.data USING btree
(sensor_id, date, version_Id);
CREATE INDEX data_version_id_idx
ON public.data USING btree
(version_id);
CREATE INDEX data_date_idx
ON public.data USING btree
(date);
CREATE INDEX data_sensor_id_idx
ON public.data USING btree
(sensor_id);
CREATE INDEX data_date_sensor_id_idx
ON public.data USING btree
(date, sensor_id);
答案 0 :(得分:3)
greatest-n-per-group(其中n = 1)查询通常最好使用distinct on ()
完成:
SELECT distinct on (sensor_id, date) *
FROM data
order by sensor_id, date, version_id DESC;
答案 1 :(得分:1)
如果您真的想从每个日期和会话中仅获取一条记录,那么@a_horse的DISTINCT ON
答案就是解决方法。但是,假设有联系,您可以在此处进行排名分析功能:
SELECT data_id, date, value, sensor_id, version_id
FROM
(
SELECT *,
RANK() OVER (PARTITION BY sensor_id, date ORDER BY version_id DESC) rank
FROM yourTable
) t
WHERE rank = 1;