mysql - 需要 2 个 MySql 查询的帮助。加入与子查询

标签 mysql

我有 2 个表:

用户:id,姓名 消息:sender_id, receiver_id, message, read_at, created_at

我需要检索 2 个结果,我正试图找到最佳解决方案。我已经包含了我在最后使用的查询。

  1. 我需要检索用户列表,并且每个用户都有可用的信息是否有来自每个用户(他们作为发件人,我作为收件人)的任何未读消息以及是否有任何已读消息我们之间(他们发送我是接收者或者我发送他们是接收者)

  2. 我需要与上面相同,但只需要我们之间有任何消息传递的成员,首先按未读消息排序,然后按最后收到的消息排序。

请问有什么建议吗?这应该通过连接还是子查询来完成?

第一种情况我不需要计数,我只需要知道是否有至少一条未读消息。我正在发布代码和我当前的查询,请在有机会时查看:

顺便说一句,一切都是我想要的第一次查询方式。

我担心的是:在第二个查询中,我想通过 messages.created_at 进行排序,但我认为我不能通过分组来做到这一点?而且我也不知道这种方法是否是最优化和最快速的。

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
)

INSERT INTO `user` VALUES (1,'User 1'),(2,'User 2'),(3,'User 3'),(4,'User 4'),(5,'User 5');

CREATE TABLE `message` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `sender_id` bigint(20) DEFAULT NULL,
  `receiver_id` bigint(20) DEFAULT NULL,
  `message` text,
  `read_at` datetime DEFAULT NULL,
  `created_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
)

INSERT INTO `message` VALUES (1,3,1,'Messge',NULL,'2010-10-10 10:10:10'),(2,1,4,'Hey','2010-10-10 10:10:12','2010-10-10 10:10:11'),(3,4,1,'Hello','2010-10-10 10:10:19','2010-10-10 10:10:15'),(4,1,4,'Again','2010-10-10 10:10:25','2010-10-10 10:10:21'),(5,3,1,'Hiii',NULL,'2010-10-10 10:10:21');

SELECT u.*, m_new.id as have_new, m.id as have_any
FROM user u 
LEFT JOIN message m_new ON (u.id = m_new.sender_id AND m_new.receiver_id = 1 AND m_new.read_at IS NULL)
LEFT JOIN message m ON ((u.id = m.sender_id AND m.receiver_id = 1) OR (u.id = m.receiver_id AND m.sender_id = 1))
GROUP BY u.id

SELECT u.*, m_new.id as have_new, m.id as have_any
FROM user u 
LEFT JOIN message m_new ON (u.id = m_new.sender_id AND m_new.receiver_id = 1 AND m_new.read_at IS NULL)
LEFT JOIN message m ON ((u.id = m.sender_id AND m.receiver_id = 1) OR (u.id = m.receiver_id AND m.sender_id = 1))
where m.id IS NOT NULL
GROUP BY u.id

最佳答案

第一个查询:

SELECT  u.*,
        EXISTS
        (
        SELECT  NULL
        FROM    message
        WHERE   sender_id = u.id
                AND receiver_id = 1
                AND read_at IS NULL
        ) have_new,
        EXISTS
        (
        SELECT  NULL
        FROM    message
        WHERE   (
                sender_id = u.id AND receiver_id = 1
                OR sender_id = 1 AND receiver_id = u.id
                )
                AND read_at IS NOT NULL
        ) have_any
FROM    user u

第二个查询:

SELECT  u.*,
        EXISTS
        (
        SELECT  NULL
        FROM    message
        WHERE   sender_id = u.id
                AND receiver_id = 1
                AND read_at IS NULL
        ) have_new,
        (
        SELECT  created_at
        FROM    message
        WHERE   (
                sender_id = u.id AND receiver_id = 1
                OR sender_id = 1 AND receiver_id = u.id
                )
        ORDER BY
                created_at DESC
        LIMIT 1
        ) last_message
FROM    (
        SELECT  DISTINCT sender_id AS party
        FROM    message
        WHERE   receiver_id = 1
        UNION
        SELECT  DISTINCT receiver_id
        FROM    message
        WHERE   sender_id = 1
        ) m
JOIN    user u
ON      u.id = m.party
ORDER BY
        have_new DESC, last_message DESC

创建以下索引:

messages (sender_id, receiver_id, last_message)
messages (receiver_id, sender_id, last_message)

关于mysql - 需要 2 个 MySql 查询的帮助。加入与子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4546709/

相关文章:

mysql - 基于 .net MVC 的 Sphinx

MySQL基于单表中具有多个GROUP BY的两列进行多重计数

php - 结合2条sql语句

php - 使用 HTTP-POST 方法将 MySQL 从 xcode 更新为 PHP

php - 使用 aFetch($sql) 问题用 php 从 mysql db 中获取所有行

mysql - 每个月每个唯一 ID 的累计总和

php - 如何使用 for 循环和 union all 按列进行分组

mysql - 如何在Mysql中检索匹配和不匹配的记录?

由 mySQL 日期填充的 PHP 日历

php - 在 php 编码中将 php 连接到下拉列表