【问题标题】:Retrieving data from PostgreSQL DB in a more efficient way以更有效的方式从 PostgreSQL 数据库中检索数据
【发布时间】:2021-01-24 17:44:38
【问题描述】:

我正在使用 PostgreSQL 开发实时聊天应用程序,但遇到以下问题:

当用户登录时,我需要获取所有不是登录用户的用户,以便将它们显示在应用程序的侧边栏上。

每个用户下方应显示登录用户或其他用户发送的最新消息。

我正在尝试执行有效的查询,以便一次检索所有用户及其最新消息,但没有成功。

这是我的表格:

我一开始尝试做这样的事情:

SELECT users.id, users.first_name, users.last_name, users.image, messages.sender_id, messages.recipient_id, messages.content
FROM users LEFT JOIN messages on users.id = messages.sender_id OR users.id = messages.recipient_id
WHERE (messages.sender_id = 1 OR messages.recipient_id = 1) AND users.id != 1
GROUP BY users.id
ORDER BY messages.created_at DESC;

我得到了这个错误:

  • “1”是指登录的用户ID

我的临时解决方案是从数据库中获取所有用户,在服务器上映射它们并执行另一个查询,该查询使用 - ORDER BY created_at DESC LIMIT 1 在用户之间发回最新消息。

我确信有更有效的方法,如果有任何帮助,我将不胜感激!

【问题讨论】:

  • 我修复了你的数据库标签。请仅使用您真正使用的数据库进行标记。
  • 请将您的查询以文本形式发布。这是一个直截了当的问题; tldr 是“使用相关子查询”,当我可以复制查询时,我将包含一个示例。
  • GROUP BY 在发布的查询中在哪里?这个发布的查询是应用中使用的临时解决方案吗?这里的问题到底是什么?当前查询运行缓慢吗?请更好地描述但没有成功。错误?不想要的结果?进程缓慢?

标签: sql postgresql datetime case greatest-n-per-group


【解决方案1】:

如果我没听错的话,你可以使用条件逻辑来选择登录用户和任何其他用户之间交换(发送或接收)的消息,然后加入到相应的用户记录中。要获取每个用户的最新消息,distinct on 在 Postgres 中很方便。

考虑:

select distinct on (u.id) u.id, ... -- enumerate the columns you want here
from (
    select m.*, 
        case when sender_id = 1 then recipient_id else sender_id end as other_user_id
    from messages m
    where 1 in (m.sender_id, m.recipient_id)
) m
inner join users u on u.id = m.other_user_id
order by u.id, m.created_at desc

我们也可以用横向连接来表达:

select distinct on (u.id) u.id, ... 
from messages m
cross join lateral (values 
    (case when sender_id = 1 then recipient_id else sender_id end as other_user_id)
) as x(other_user_id)
inner join users u on u.id = x.other_user_id
where 1 in (m.sender_id, m.recipient_id)
order by u.id, m.created_at desc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-23
    • 2010-09-25
    • 2012-08-12
    • 2015-01-28
    • 1970-01-01
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多