对于我正在开发的一个网站,我的任务是实现一个私有(private)消息系统。 我的基本场景是,数据库中有多个消息条目,每个条目包含一个发送者和一个接收者。然而,“当前用户”应该能够看到这两条消息,因为它们都与他相关。 问题是,我只对其他用户的数据感兴趣,而不是我自己的数据。但“当前用户”既可以是发件人,也可以是收件人。
我在这里的查询完成了这项工作,但它并不优雅。我加入两个用户,然后使用 IF 决定我应该获取哪些数据。
SELECT
IF(m.sender = ?, 1, 0) AS isself,
IF(m.sender = ?, u_recipient.id, u_sender.id) AS other_id,
IF(m.sender = ?, u_recipient.displayName, u_sender.displayName) AS other_name,
IF(m.sender = ?, u_recipient_avatar.url, u_sender_avatar.url) AS other_avatar,
m.text AS text
FROM messages AS m
LEFT JOIN user AS u_sender
ON u_sender.id = m.sender
LEFT JOIN avatars AS u_sender_avatar
ON u_sender_avatar.id = u_sender.avatarId
LEFT JOIN user AS u_recipient
ON u_recipient.id = m.recipient
LEFT JOIN avatars AS u_recipient_avatar
ON u_recipient_avatar.id = u_recipient.avatarId
WHERE ( m.sender = ? OR m.recipient = ? )
AND UNIX_TIMESTAMP(m.timestamp) > ?
ORDER BY m.timestamp ASC
LIMIT 100
所以基本上,我的问题是,有没有更优雅的方法来做到这一点?将发送者/接收者 int 存储到 1 个单个表中以便在连接中重用?否则,这是否会消耗性能(连接我不需要的表?)。或者我应该在应用程序本身中将它们分开?
提前致谢!
最佳答案
看到我不允许编辑其他答案,该答案部分正确。 我的答案是基于 Ben 的答案,但删除了语法错误。
SELECT d.isself, other_id, u.displayName AS other_name, a.url AS other_avatar, text
FROM
(
SELECT 0 AS isself, m.sender AS other_id, m.timestamp, m.text
FROM messages AS m
WHERE m.recipient = ?
UNION
SELECT 1 AS isself, m.recipient AS other_id, m.timestamp, m.text
FROM messages AS m
WHERE m.sender = ?
) AS d
LEFT JOIN user AS u
ON u.id = d.other_id
LEFT JOIN avatars AS a
ON a.id = u.avatarId
WHERE UNIX_TIMESTAMP(timestamp) > ?
ORDER BY m.timestamp ASC
LIMIT 100
关于MySQL 连接两个潜在的字段名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21484966/