带计数和行的 MySQL 查询

标签 mysql

我有一个消息表,我想知道实现以下结果最有效的查询是什么:

请注意,如果线程是第一个消息,则线程字段为 null,所有其他消息都链接到该线程,且其 emid

CREATE TABLE `messages` (
    `emid` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `emitter` BIGINT(20) NOT NULL,
    `receiver` BIGINT(20) NOT NULL,
    `thread` BIGINT(20) DEFAULT NULL,
    `opened` TINYINT(4) DEFAULT 0,
    `message` BLOB NOT NULL,
    `timecard` DATETIME DEFAULT CURRENT_TIMESTAMP,
    ADD CONSTRAINT `efk` FOREIGN KEY (`emitter`) REFERENCES `members` (`user_id`),
    ADD CONSTRAINT `rfk` FOREIGN KEY (`receiver`) REFERENCES `members` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我想获取给定接收器的第一行,包括其消息计数。例如,假设用户有 4 条未打开的消息(未读)和两条回复。我想获得该线程下收到的第一条消息以及双方的回复总数。起初我想到了子查询,但这似乎会表现得很糟糕。

以下内容为用户选择线程(接收者 = id)

    SELECT * FROM `messages` WHERE thread IS NULL AND receiver = 2 ORDER BY timecard DESC

这个获取给定线程下的消息计数

        SELECT COUNT(*) FROM `messages` WHERE thread = 20

最佳答案

加入您的两个查询:

SELECT m1.*, IFNULL(COUNT(m2.emid), 0) AS replies
FROM messages AS m1
LEFT JOIN messages AS m2 ON m2.thread = m1.emid
WHERE m1.thread is NULL
GROUP BY m1.emid

WHERE 子句仅从表 m1 中选择每个线程的起始消息。

LEFT JOIN 然后将其与该线程的所有回复关联起来,使用 thread 列将它们链接回原始消息。我使用了LEFT JOIN,以便包含没有回复的消息。

COUNT(m2.emid) 然后计算相关行数,即线程中的回复数。 COUNT() 仅计算非空值;如果没有回复,LEFT JOIN 会将此列设置为 NULL,这样您将得到的计数为 0

关于带计数和行的 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48776447/

相关文章:

php - Phinx 迁移 sqlite 内存 phpunit

mysql - Tableau 中的跨架构联接

mysql - CakePHP 3.x - 如何通过另一个关联的字段过滤一个关联?

mysql - 在 visual studio 中使用 MySQL 并在运行时更改连接

python - 在 mysqldb 和 flask 中使用游标

mysql - MySQL 命令 SELECT 的奇怪行为

php - 如何将数据库中的图像调成每行10张图像?

mysql - 连接动态sql查询

mysql - Java 中的 EBean - 使用 @MappedSuperclass 进行继承

mysql - SQL仅选择列上具有最大值的行