0

我有数百万行的表,需要获取特定 ID 的最后一行

例如具有 device_id = 123 的最后一行和具有 device_id = 1234 的最后一行

因为表格太大了,订购需要很多时间,是否可以选择最后 200 个而不订购表格,然后只订购这 200 个并获取我需要的行。

我该怎么做?

预先感谢您的帮助!

更新

我的 PostgreSQL 版本是 9.2.1

样本数据:

time                      device_id         data       data ....
"2013-03-23 03:58:00-04" | "001EC60018E36" | 66819.59 | 4.203
"2013-03-23 03:59:00-04" | "001EC60018E37" | 64277.22 | 4.234
"2013-03-23 03:59:00-04" | "001EC60018E23" | 46841.75 | 2.141
"2013-03-23 04:00:00-04" | "001EC60018E21" | 69697.38 | 4.906
"2013-03-23 04:00:00-04" | "001EC600192524"| 69452.69 | 2.844
"2013-03-23 04:01:00-04" | "001EC60018E21" | 69697.47 | 5.156
....

请参阅此数据的 SQLFiddle

因此,如果 device_id = 001EC60018E21 我想要具有该 device_id 的最新行。具有该 device_id 的最后一行是我想要的行是受让人,但它可能是也可能不是表的最后一行。

4

2 回答 2

2

就个人而言,我会在device_id降序上创建一个复合索引time

CREATE INDEX table1_deviceid_time ON table1("device_id","time" DESC);

然后我会使用一个子查询来查找time每个的最高值,device_id并将子查询结果与主表连接起来device_idtime找到相关数据,例如:

SELECT t1."device_id", t1."time", t1."data", t1."data1"
FROM Table1 t1
INNER JOIN (
  SELECT t1b."device_id", max(t1b."time") FROM Table1 t1b GROUP BY t1b."device_id"
) last_ids("device_id","time") 
ON (t1."device_id" = last_ids."device_id" 
    AND t1."time" = last_ids."time");

请参阅此 SQLFiddle

维护每个设备 ID 的最高时间戳的基于触发器的物化视图可能会有所帮助。但是,如果由于连接争夺更新锁,大多数连接可以插入给定设备 ID 的数据,这将导致并发问题。如果你不知道什么时候会出现新的设备 ID,因为你必须做一个 upsert,这也是一种痛苦——这是非常低效和笨拙的事情。此外,汇总表创建的额外写入负载和自动清理工作可能不值得;为更昂贵的查询付出代价可能会更好。

顺便说一句,time对于列来说这是一个糟糕的名称,因为它是一个内置的数据类型名称。如果可以,请使用更合适的东西。

于 2013-04-05T02:03:06.963 回答
1

获取每个 device_id 的“最后”行的一般方法如下所示。

select *
from Table1 
inner join (select device_id, max(time) max_time
            from Table1
            group by device_id) T2
   on Table1.device_id = T2.device_id
  and Table1.time = T2.max_time;

在不使用 ORDER BY 的情况下获取“最后一个”200 个 device_id 数字实际上并不实用,但不清楚您为什么首先要这样做。如果 200 是一个任意数字,那么您可以通过取一个基于任意时间的表子集来获得更好的性能。

select *
from Table1 
inner join (select device_id, max(time) max_time
            from Table1
            where time > '2013-03-23 12:03'
            group by device_id) T2
on Table1.device_id = T2.device_id
and Table1.time = T2.max_time;
于 2013-04-05T02:03:24.713 回答