优化的SQL查询以获取用户信息的上次修改日期

时间:2019-03-27 08:16:30

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

我正在尝试显示所有用户的上次修改日期/时间。 用户信息分布在多个表中(所有表都包含last_modified_date列)。 下表如下。 User_Details, User_Contact_Details, User_Social_Media_Details。

我的第一个想法是执行如下UNION ALL。

select user.id, user.last_modified_date from 
(
(select id, last_modified_date from "User_Details" order by id)
UNION ALL
(select user_id as id, last_modified_date from "User_Contact_Details" order by id)
UNION ALL
(select user_id as id, last_modified_date from "User_Social_Media_Details" order by id)
) as user 
where user.last_modified_date is not null
order by user.id, user.last_modified_date desc

这将为我提供所有用户及其上次修改日期的降序排列,然后为每个用户执行前1名。 这让我想知道这是否是正确且优化的方法。

非常感谢您的帮助/建议。

2 个答案:

答案 0 :(得分:1)

如果我正确理解了这个问题,那么您希望每个用户的最新修改日期。归结为一个问题(n = 1)。通常在Postgres中使用distinct on ()可以解决这些问题:

select distinct on (usr.id) id, last_modified_date 
from 
(
  select id, last_modified_date 
  from "User_Details" 

  UNION ALL

  select user_id as id, last_modified_date 
  from "User_Contact_Details" 

  UNION ALL

  select user_id as id, last_modified_date 
  from "User_Social_Media_Details" 
) as usr 
where last_modified_date is not null
order by id, last_modified_date desc;

并集查询中的order by并不是真正必要的,除非您已经想要在其中预先过滤用户ID,这可能会更有效:

select distinct on (usr.id) id, last_modified_date 
from 
(
  select distinct on (id) id, last_modified_date 
  from "User_Details" 
  order by id, last_modified_date desc

  UNION ALL

  select distinct on (user_id) user_id as id, last_modified_date 
  from "User_Contact_Details" 
  order by user_id, last_modified_date desc

  UNION ALL

  select distinct on (user_id) user_id as id, last_modified_date 
  from "User_Social_Media_Details" 
  order by user_id, last_modified_date desc

) as usr 
where last_modified_date is not null
order by id, last_modified_date desc;

您仍然需要在外部查询中使用distinct on (),因为可以从UNION的不同分支返回相同的用户ID。


user是保留关键字,请避免将其用作标识符。而且,如果这样做,则必须引用它"user"以避免与内置函数user

混淆。

如果"User_Details"表是其他人引用的“主”表,并且您只想获取每个用户ID的最新修改日期,无论发生在哪个表中,也可以使用分组依据:

select id, 
       max(greatest(ud.last_modified_date, ucd.last_modified_date, usmd.last_modified_date)) as latest_modification
from "User_Details" ud
  left join "User_Contact_Details" ucd on ucd.user_ud = ud.id
  left join "User_Social_Media_Details"  usmd on usmd.user_id = ud.id
group by id;

答案 1 :(得分:0)

在每个表上独立运行:

select u.id, u.last_modified_date 
from ((select id, last_modified_date 
       from "User_Details" 
       order by last_modified_date desc
       limit 1
      ) union all
      (select user_id, last_modified_date
       from "User_Contact_Details" 
       order by last_modified_date desc
       limit 1
      ) union all
      (select user_id, last_modified_date
       from "User_Media_Details" 
       order by last_modified_date desc
       limit 1
      ) 
     ) u 
order by last_modified_date desc
limit 1;

通过在子查询中运行limit,数据库引擎仅返回一行并可以使用索引。

编辑:

如果您需要 each 个用户而不是全部用户使用,则在子查询和外部查询中使用group by

select u.id, max(u.last_modified_date) 
from ((select id, max(last_modified_date) as last_modified_date
       from "User_Details" 
       group by id
      ) union all
      (select user_id, max(last_modified_date) as last_modified_date
       from "User_Contact_Details" 
       group by user_id
      ) union all
      (select user_id, max(last_modified_date) as last_modified_date
       from "User_Media_Details" 
       group by user_id
      ) 
     ) u 
group by user_id;