我有以下查询根据一系列约束筛选出线程行:
SELECT *
FROM threads th
JOIN v_threads_with_tags AS twt /*Only if filtering by tags*/
ON th.thread_id = twt.thread_id
JOIN v_friends AS f /*Only if filtering to threads from friends*/
ON th.owner_id = f.friend
LEFT JOIN v_visible_threads AS v
ON v.thread_id = th.thread_id
WHERE (v.viewer_id = 43 || v.viewer_id IS NULL)
&& (v.friend_id = 43 || v.friend_id IS NULL)
&& user = 43;
&& tag_name IN ('foo','bar')
部分查询我没有机会测试,但我可以肯定地说标签名称没有被完全过滤。此查询将返回与此类似的结果集(仅列出相关列):
thread_id | tag_name
1 foo
1 bar
2 foo
3 foo
我想要一个只有thread_id的结果集,它们链接到查询中列出的所有标签,显然我不能有重复项。在上面的例子中,我想要一个只有一个线程#1实例的结果集。
我在stackoverflow上看过类似的问题(请在将其标记为重复之前阅读),虽然提供的解决方案差异很大,但一般路径似乎经常涉及在查询结尾添加以下语句:
HAVING COUNT('tag_name') = 2
我也尝试了以下类似的查询:
SELECT th.thread_id,th.owner_id,th.message,th.time,tag_name,viewer_id,v.friend_id
FROM threads th
LEFT JOIN v_visible_threads AS v
ON v.thread_id = th.thread_id
WHERE (v.viewer_id = 43 || v.viewer_id IS NULL)
&& (v.friend_id = 43 || v.friend_id IS NULL)
&& th.thread_id IN
(
SELECT thread_id FROM v_threads_with_tags
WHERE tag_name IN ('foo','bar')
HAVING COUNT(tag_name) = 2
)
我无法理解COUNT()在其中任何一个中的用法。在此结果集中,列tag_name有四个值,因此无论特定行中tag_name的值是什么,我都希望COUNT(tag_name)返回4。这实际上是它返回的值,因此该语句会导致查询返回一个空集。
尽管如此,我看到这个语句在任何时候都被用来解决这类问题,所以我必须假设每个人都正确地使用它并且我错过了一些东西。
有人可以向我解释我是否正确理解COUNT,以及我可以使用哪些方法来完成查询?
答案 0 :(得分:1)
如果您希望线程具有所有标记,则无法仅使用where
子句获得该标记。相反,按thread_id
聚合并计算每个标记的匹配数。返回对于您关心的每个标记至少有一个匹配的线程:
SELECT th.thread_id
FROM threads th JOIN
v_threads_with_tags twt /*Only if filtering by tags*/
ON th.thread_id = twt.thread_id JOIN
v_friends f /*Only if filtering to threads from friends*/
ON th.owner_id = f.friend LEFT JOIN
v_visible_threads AS v
ON v.thread_id = th.thread_id
WHERE (v.viewer_id = 43 || v.viewer_id IS NULL) and
(v.friend_id = 43 || v.friend_id IS NULL) and
user = 43
group by th.thread_id
having sum(tag_name = 'foo') > 0 and
sum(tag_name = 'bar') > 0;