我在表用户和标签之间具有一对多关系:
Users:
id username
--------------
1 Bob
2 Alice
3 Eve
Tags:
id user_id name
--------------------
1 1 java // Bobs tags...
2 1 java script
3 1 C#
4 2 java // Alices tags...
5 3 java // Eves tags...
6 3 java script
我的目标是仅提取带有标签Java或Java脚本的所有用户,而不提取具有Java,Java脚本和C#的用户。
作为查询的输出,我希望收到以下结果:
Result:
id username
--------------
2 Alice
3 Eve
我曾尝试使用SQL one-to-many relationship - How to SELECT rows depending on multiple to-many properties?中的查询,但正如我注意到的,其背后的想法有点不同
一个有效的,尽管输入很长,但选项使用exists
:
select u.*
from users u
where
not exists(select 1 from tags t where t.user_id = u.id and t.name = 'C#')
and exists(select 1 from tags t where t.user_id = u.id and t.name = 'java ')
and exists(select 1 from tags t where t.user_id = u.id and t.name = 'java script')
[在tags(user_id, name)
上有索引,这应该非常快。
您可以使用条件聚合逻辑来获取标签:
select t.user_id
from tags t
where t.name in ('java', 'java script', 'C#')
group by t.user_id
having sum(case when t.name = 'C#' then 1 else 0 end) = 0; -- no C#
引入user_name
只是附加联接。
似乎HAVING
可以在这里使用:
SELECT U.id,
U.username
FROM dbo.Users U
JOIN dbo.Tags T
GROUP BY U.ID,
U.username
HAVING COUNT(CASE T.[name] WHEN 'java' THEN 1 END) > 0
AND COUNT(CASE T.[name] WHEN 'java script' THEN 1 END) > 0
AND COUNT(CASE WHEN T.[name] NOT IN ('java','java script') THEN 1 END) = 0;