【问题标题】:MySQL Data from 3 tables来自 3 个表的 MySQL 数据
【发布时间】:2011-08-29 21:30:31
【问题描述】:

我有三个与消息传递系统相关的 MySQL 表。与我的问题相关的每个表的架构和示例数据如下所示:

`messages`:
+----+---------+----------+
| id | subject | senddate |
+----+---------+----------+
| 1  | Testing | 12344555 |
+----+---------+----------+

`message_senders`:
+------------+---------+---------+
| message_id | user_id | trashed |
+------------+---------+---------+
|      1     |    1    |    1    |
+------------+---------+---------+

`message_recipients`:
+------------+---------+------+----------+---------+
| message_id | user_id | type | readdate | trashed |
+------------+---------+------+----------+---------+
|      1     |    1    |  to  | 12344555 |    1    |
+------------+---------+------+----------+---------+
|      2     |    1    |  cc  | 12344555 |    1    |

我的问题是如何选择用户发送或接收的所有邮件,其中已删除参数设置为 1,而不选择重复邮件。例如,考虑以下场景:

我想获取被user_id1 丢弃的所有邮件的邮件ID,但我不想检索重复的ID(例如,在上面的数据中,user_id1 是@987654324 的发件人和收件人@ 1. 我不想返回 1 的 message_id 两次,但想获取该用户的所有消息。

我想我需要结合使用JOIN 和UNION,但是经过一整天的 PHP,我的大脑无法正常工作!

【问题讨论】:

  • 为收件人设置一个单独的表是有意义的,但为什么要设置一个单独的发件人表呢?这将允许单个消息的多个发件人,这没有多大意义。
  • 消息可以由用户组发送,因此当以这种方式发送消息时,会为组中的每个用户输入单独的记录。

标签: php mysql database join union


【解决方案1】:

试试这个,看看它是否只为消息表中的每条消息返回一行...

    select * from messages 
left join message_senders on messages.id = message_senders.message_id 
left join message_recipients on messages.id = message_recipients.message_id 
where message_senders.trashed = 1 or message_recipients.trashed = 1 and messages.user_id = <value>

【讨论】:

    【解决方案2】:

    假设您已经想到了查询 - 我只是提示您可以使用 DISTINCT 关键字来强制数据库不返回重复项。 我相信你可以自己解决,因为自我结论最有效。

    另外,一条建议 - 始终将日期存储为 datetime 或 date 而不是 int。您可以避免夏令时问题,并且可以使用 MySQL 提供的各种日期函数。 日期在内部保存为 4 字节整数,与 int 字段相同。

    【讨论】:

    • 感谢您的帮助,NB。据我所知, DISTINCT 只能用于一列。此外,日期实际上是一个 Unix 时间戳。
    • 是的,unix 时间戳是一个整数,你可能将它存储为 INT 或 TIMESTAMP。但是,当您想将间隔增加到 7 天或 3 周或其他任何时间时,DATE 或 DATETIME 仍然要好得多。您不必计算秒数即可将其包含在计算中。如果您选择 DISTINCT message_id 并在其各自的键上连接其他表,您将不会得到重复。
    【解决方案3】:

    给你,试一试:

    select distinct m.id
    from messages m
    left join message_senders s on m.id = s.message_id
    left join message_recipients r on m.id = r.message_id
    where ((s.user_id = 1 and s.trashed = 1) or (r.user_id = 1 and r.trashed = 1))
    

    【讨论】:

      【解决方案4】:

      我想到的解决方案是使用UNIONd 子查询:

      SELECT DISTINCT * FROM messages WHERE id IN (
          (SELECT message_id FROM message_recipients WHERE user_id=1 AND trashed=1)
        UNION
          (SELECT message_id FROM message_senders WHERE user_id=1 AND trashed=1)
      )
      

      【讨论】:

      • 这将返回没有不同子句的重复项。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-16
      • 1970-01-01
      • 2016-04-29
      相关资源
      最近更新 更多