我有两个具有MTM关系的对象
User
------------
id
name
Location
------------
id
latitude
longitude
date_created
userlocation
------------
id
fk_user_id
fk_location_id
访问数据时,我通常只需知道与用户关联的最新位置,但我确实想要存储用户以前的所有位置。写入读取比率约为1:10
我相信这是一种非常常见的持久性模式,我想知道最接近它的标准方法是什么?是做JOIN
并形成新视图吗?
答案 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