我的查询:
SELECT content.*, activity_log.content_id FROM content
LEFT JOIN activity_log
ON content.id = activity_log.content_id
AND sess_id = '$sess_id'
WHERE activity_log.content_id IS NULL
AND visibility = $visibility
AND content.reported < ".REPORTED_LIMIT."
AND content.file_ready = 1
LIMIT 1
该查询的目的是从内容表中获取用户未查看过的 1 行(由 session_id 标识),但它仍然返回已查看过的内容。怎么了? (我检查了表格以确保 content_ids 在那里)
注:我觉得这样比使用子查询更高效,思想?
最佳答案
问题显然出在您的 JOIN 条件中。当您对内部联接结果感兴趣时,您正在使用的优化(将条件应用于基表)很有意义,但如果是外部联接,则读取如下:查找 content
和activity_log
内容 ID 匹配且 session ID 匹配时的行,当内容 ID 的日志丢失或内容 ID 不丢失时返回 activity_log
行的空值,但是 session ID 不是指定的。这几乎不是您想要的。
您的查询应如下所示:
SELECT content.*, activity_log.content_id
FROM (
SELECT *
FROM content
WHERE sess_id = '$sess_id'
AND visibility = $visibility
AND file_ready = 1
AND reported < ".REPORTED_LIMIT."
) as content
LEFT JOIN activity_log
ON content.id = activity_log.content_id
WHERE activity_log.content_id IS NULL
LIMIT 1;
如果性能不是最优的,可以考虑在(sess_id, visibility, fileready, reported)上创建复合索引。
关于mysql使用左外连接过滤结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2660552/