我正在建立一个讨论区,我希望得到一个未读主题列表。
如果主题中最后一篇文章的created_at日期时间大于当前登录用户上次查看此主题的时间,则主题应该是未读和选中的。
http://sqlfiddle.com/#!2/4e2e99/1 如果删除所有用户视图插入,则应列出所有主题。
我有三张桌子:
主题
topic_posts
topic_user_views
到目前为止我的查询(但不起作用):
SELECT DISTINCT `topics`.`id`, `topics`.`name`
FROM `topics`
INNER JOIN `topic_user_views`
ON `topic_user_views`.`topic_id` = `topics`.`id`
INNER JOIN `topic_posts`
ON `topic_posts`.`topic_id` = `topics`.`id`
WHERE `topic_posts`.`created_at` > `topic_user_views`.`created_at`
AND `topic_user_views`.`user_id` = 1
ORDER BY `id` DESC
我不知道如何比较某个主题的上一篇文章的created_at列帖子与该用户上次查看该主题的时间。
答案 0 :(得分:1)
这是一种方法。我们将使用exists来测试在创建上一个主题帖子之前是否查看了主题。看到sql fiddle - http://sqlfiddle.com/#!2/4e2e99/11
select t.id as topic_id, t.name as topic_name
from topics t
where not exists(
select tuv.topic_id, max(tuv.created_at) as last_view, max(tp.created_at) as last_post
from topic_user_views tuv
inner join topic_posts as tp
on tuv.topic_id=tp.topic_id and tuv.created_at > tp.created_at
group by topic_id
having t.id=topic_id)
ORDER BY id DESC
答案 1 :(得分:1)
以下是我提出的建议:
SELECT t1.topic_id, t3.account_user_id, t1.created_at last_post_date, t4.created_at as last_seen_date
FROM topic_posts t1
INNER JOIN (SELECT topic_id, MAX(created_at) as created_at
FROM topic_posts
GROUP BY topic_id) t2
USING (topic_id, created_at)
INNER JOIN topic_user_views t3
USING (topic_id)
INNER JOIN (SELECT topic_id, account_user_id, created_at
FROM topic_user_views
INNER JOIN (SELECT topic_id, account_user_id, MAX(created_at) as created_at
FROM topic_user_views
GROUP BY topic_id, account_user_id) _
USING (topic_id, created_at, account_user_id)) t4
ON t1.topic_id = t4.topic_id and t3.account_user_id = t4.account_user_id and t3.created_at = t4.created_at
WHERE t1.created_at > t4.created_at
AND t3.account_user_id = 1;
这个想法是加入主题(t2)中最后发布的消息的日期和用户在主题中最后看到的消息的日期(t4),然后你只需要过滤掉你的结果不想要。
如果我没有弄错,在您提供的SQLFiddle中,没有用户尚未看到过的主题,因此不会返回任何内容。我稍微修改了它(you can see it here),它似乎按照需要工作。
要考虑用户从未查看过的主题,我认为最佳解决方案是将account
表与RIGHT OUTER JOIN
一起使用。类似于:
SELECT t1.topic_id, t3.account_user_id, t1.created_at last_post_date, t4.created_at as last_seen_date
FROM topic_posts t1
INNER JOIN (SELECT topic_id, MAX(created_at) as created_at
FROM topic_posts
GROUP BY topic_id) t2
USING (topic_id, created_at)
INNER JOIN topic_user_views t3
USING (topic_id)
INNER JOIN (SELECT topic_id, account_user_id, created_at
FROM topic_user_views
INNER JOIN (SELECT topic_id, account_user_id, MAX(created_at) as created_at
FROM topic_user_views
GROUP BY topic_id, account_user_id) _
USING (topic_id, created_at, account_user_id)) t4
ON t1.topic_id = t4.topic_id and t3.account_user_id = t4.account_user_id and t3.created_at = t4.created_at
RIGHT OUTER JOIN account
ON account.user_id = t3.account_user_id
WHERE t1.created_at > t4.created_at or t4.account_user_id IS NULL
AND t3.account_user_id = 1;
我没有测试过。
答案 2 :(得分:1)
通过此示例,如果用户还没有看到任何内容,也会选择主题:
SELECT DISTINCT
`topics`.`id`,
`topics`.`name`
FROM `topics`
LEFT JOIN `topic_user_views` AS tuv
ON `tuv`.`topic_id` = `topics`.`id`
WHERE (SELECT
1
FROM topic_posts AS tp
WHERE tp.topic_id = `topics`.`id`
AND (tp.created_at > tuv.created_at
OR tuv.created_at IS NULL)
LIMIT 1)IS NOT NULL
ORDER BY `id` DESC;