MySQL加入两个潜在的字段名称

时间:2014-01-31 16:24:09

标签: mysql sql join left-join

对于我正在研究的网站,我的任务是实施私人消息系统。 我的基本方案是,数据库中有几个消息条目,每个条目包含一个发送者和一个接收者。但是,“当前用户”应该能够看到这两个消息,因为它们都与他相关。 问题是,我只对其他用户的数据感兴趣,而不是我自己的数据。但“当前用户”既可以是发件人也可以是收件人。

我在这里的查询完成了这项工作,但它并不优雅。我正在加入这两个用户,然后决定使用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个单独的表中以便在连接中重用?否则,这是一个性能困难(加入我不需要的表?)。或者我应该在应用程序本身中处理这些问题吗?

提前致谢!

2 个答案:

答案 0 :(得分:0)

如下:

SELECT 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) > ?
LIMIT 100

如果始终在用户表中找到邮件的发件人和收件人ID,则应将“LEFT JOIN user”更改为内部联接 - “JOIN user”。如果每个用户都有一个头像条目,那么该左连接也应该更改为内连接。

答案 1 :(得分:0)

看到我不被允许编辑其他答案,这是部分正确的。 我的答案是基于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