我有2个表:通过player_tags加入的玩家和标签。我想让玩家Aaron只有匹配1个或更多标签名称。在我的情况下,我希望所有玩家都有标记" test"和"新"但由于它们属于两排,我不知道该怎么做。
table: players
ID NAME
----- --------
1 AARON
2 JAMES
table: player_tags
ID PLAYER_ID TAG_ID
----- --------- --------
1 1 1
2 1 2
3 2 1
table: tags
ID NAME
----- --------
1 test
2 new
我创建了这个查询当然不起作用,因为标签'测试'并标记' new'分为2个不同的行。
SELECT "players".name, "tags".name FROM "players"
INNER JOIN "player_tags" ON "player_tags"."player_id" = "players"."id"
INNER JOIN "tags" ON "tags"."id" = "player_tags"."tag_id"
WHERE
"tags"."name" IS NOT NULL AND "tags"."name" = 'test' AND "tags"."name" = 'new'
我希望将播放器1作为响应,因为它匹配两个标签。如果我改变了' AND'到'或者'好吧,我得到了两个球员,但这不是我想要的。我使用postgres BTW。
答案 0 :(得分:4)
select p.name as player_name, string_agg(t.name, ', ') as tags
from players p
join player_tags pt ON pt.player_id = p.id
join tags t ON t.id = pt.tag_id
where t.name in ('new', 'test')
group by p.name
having count(t.id) > 1
上面实现了“如果它匹配一个或多个标签名称”部分,那么它将返回那些至少其中一个标签的玩家。
如果您只想要那些拥有这两个标签的玩家,您可以使用:
select p.name as player_name, string_agg(t.name, ', ') as tags
from players p
join player_tags pt ON pt.player_id = p.id
join tags t ON t.id = pt.tag_id
group by p.name
having array_agg(t.name order by t.name) = array['new', 'test']
请注意,您需要按字母顺序指定数组中的标记名称。
答案 1 :(得分:2)
试试这个,我还没有postgres进行测试,告诉我是否存在语法错误。
在ARRAY['test', 'new']
中,您可以添加所需的标记名称。
select player, array_agg(tag) as tags from (
SELECT players.name AS player, tags.name AS tag FROM players
INNER JOIN player_tags
ON players.ID = player_tags.PLAYER_ID
INNER JOIN tags
ON player_tags.TAG_ID = tags.ID
) t
group by player
having
ARRAY(SELECT unnest(array_agg(tag)) ORDER BY 1) = ARRAY(SELECT unnest(ARRAY['test', 'new']) ORDER BY 1)
答案 2 :(得分:1)
我对postgresql不熟悉,但是你可以为你正在寻找的每个标签加入一次播放器标签表吗?
在SQL Server中,我可以执行以下操作:
select p.name
from players p
join player_tags pt1 on p.id = pt1.player_id and pt1.tag_id = 1
join player_tags pt2 on pt1.player_id = pt2.player_id and pt2.tag_id = 2
你能做那样的事吗?
答案 3 :(得分:1)
您必须确保两个条件都成立:
with ctag as
(
select pt.player_id pid, t.name tname
from players_tags pt
inner join tags t on t.id = pt.tag_id
where tags.name in ('test','new')
)
select p.id, p.name
from players p
where exists (select 1 from ctag where pid = p.id and tname = 'test')
and exists (selet 1 from ctag where pid = p.id and tname = 'new');