我有一个消息表,我想知道实现以下结果最有效的查询是什么:
请注意,如果线程是第一个消息,则线程字段为 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/