用于访问多对多关系中的最新数据的高效模式?

时间:2016-08-28 19:50:20

标签: sql postgresql sqlalchemy greatest-n-per-group

我有两个具有MTM关系的对象

User
------------
id
name

Location
------------
id
latitude
longitude
date_created

userlocation
------------
id
fk_user_id
fk_location_id

访问数据时,我通常只需知道与用户关联的最新位置,但我确实想要存储用户以前的所有位置。写入读取比率约为1:10

我相信这是一种非常常见的持久性模式,我想知道最接近它的标准方法是什么?是做JOIN并形成新视图吗?

2 个答案:

答案 0 :(得分:0)

模式本身就是JOIN表userlocation:

SELECT t1.* 
    FROM userlocation AS t1 
    LEFT JOIN userlocation AS t2 ON t1.fk_user_id = t2.fk_user_id AND t1.fk_location_id = t2.fk_location_id AND t1.id> t2.id 
WHERE 
    t2.id IS null

基本上会发生什么事情,你试图加入表 userlocation 中的每一行相同的表,但是使用较小的键。如果它不是fk_user_id / fk_location_id组合的第一个记录,那么将使用较小的键插入一些其他记录。如果它是组中的最小键而不是连接列将返回NULL,因为没有以前的键。

在此阶段,您只需从第一个表中过滤掉具有较小键的预期列的行,即NULL。有了这个,您可以轻松地加入特定用户或位置所需的信息,以根据需要扩展查询。

答案 1 :(得分:0)

我认为您的问题已在此处得到解答:SQL join: selecting the last records in a one-to-many relationship

随着用户位置表变得非常大,该方法存在附带问题。

但就个人而言,我会通过在User中创建一个名为last_userlocation_id的额外列来接近它,当将新行添加到userlocation(在WRITE期间)时,该列将被设置为id(autoincrement)的值

如果您这样做,那么您的SQL for READ将大大简化为:

SELECT User.name, Location.latitude, Location.longitude FROM
User 
LEFT JOIN userlocation ON userlocation.id = User.last_userlocation_id
LEFT JOIN Location ON Location.id = userlocation.fk_location_id

使用LEFT JOIN而非INNER JOIN的原因是为了满足尚未录制任何位置的用户。在这种情况下,纬度和经度将为NULL