复合主键上的PostgreSQL SELECT DISTINCT

时间:2018-09-17 15:25:39

标签: postgresql composite-primary-key

我的桌子结构如下:

Column    |  Type |
id        | int   | 
version   | int   |
status_id | int   |  // can be 1 active, 2 suspended, 3 removed
update    | Timestamp |
position  | Geometry  |

Indexes:
"PK_poi" PRIMARY KEY, btree (id, version)

所以这是我的表结构,基本上会在Location发生一些事情,我将创建它,然后发生其他事情,并使用新版本更新该事件。

所以数据会像

 id         |  version  | status_id |  update              | position
 1          |  1        |   1       |  2018-09-17 10:52:48 | x,y 
 2          |  1        |   1       |  2018-09-17 10:52:48 | x,y
 2          |  2        |   1       |  2018-09-17 11:02:48 | x,y
 2          |  3        |   2       |  2018-09-17 11:22:48 | x,y
 1          |  2        |   2       |  2018-09-17 11:52:48 | x,y
 2          |  4        |   1       |  2018-09-17 12:52:48 | x,y
 1          |  3        |   3       |  2018-09-17 12:52:48 | x,y
 2          |  5        |   3       |  2018-09-17 13:52:48 | x,y
 3          |  1        |   1       |  2018-09-17 14:52:48 | x,y
 3          |  2        |   1       |  2018-09-17 14:52:48 | x,y
 4          |  1        |   1       |  2018-09-17 16:52:48 | x,y
 4          |  2        |   1       |  2018-09-17 16:52:48 | x,y

因此,我尝试进行distint选择,该选择基于时间戳在指定的时间间隔内返回“最新”版本。但是,只有在“最新”版本的状态不是“已暂停”或“已删除”时。

因此,如果我在17:52查询数据库,并说在过去一小时内给我最新的事件,我会期望:

  id         |  version  | status_id |  update              | position
  4          |  2        |   1       |  2018-09-17 16:52:48 | x,y

但是,如果我说的话,请告诉我最近24小时以来的最新活动

  id         |  version  | status_id |  update              | position
  3          |  2        |   1       |  2018-09-17 14:52:48 | x,y
  4          |  2        |   1       |  2018-09-17 16:52:48 | x,y

由于复合键,我对如何执行此操作感到非常困惑。能否请您指出我应该读什么书?

提前谢谢

1 个答案:

答案 0 :(得分:1)

您需要row_number才能获取每个位置的最新事件。

SELECT *
FROM ( SELECT *, 
              ROW_NUMBER() OVER (PARTITION BY id ORDER BY "update" DESC ) as rn
                                          -- ^^^ create a group for each id
       FROM yourTable           
       WHERE status_id = 1
         -- optional if you want the events in a time range
         AND "update" > current_timestamp - interval '1 day -- filter the last 24 h events
     ) as Q

-- optional if you want all events remove it.
WHERE rn = 1 -- filter the last one of each id because is order by update desc