查找玩过这两款游戏的玩家

Find players that played both games

我想获取同时下国际象棋和跳棋的人的playerid。 我有一个 table 是这样的:

playerid   game         website
a1         chess        www.abc.com
a2         checkers     www.cba.com
a1         checkers     www.abc.com
b2         chess        www.abc.com
b1         chess        www.abc.com
a3         checkers     www.aaa.com
b2         checkers     www.abc.com

期望的输出(应排除 a3 和 b1)

a1
b2
select game, playerid, website
from player_db
where (game= 'chess' or game= 'checkers') and website='abc.com'
group by playerid ;

这是我的 SQL,但它似乎并没有得到这两种游戏 -- 它选择国际象棋或西洋跳棋。

select DISTINCT t1.player_id from daily_player as t1
        where exists (select 1 from daily_player as t2 where t1.player_id = t2.player_id and game = 'chess')
        and exists (select 1 from daily_player as t3 where t1.player_id = t3.player_id and game = 'checkers')
        and  website='abc.com'

使用 OR 时的问题是,还会发现每个条目都只满足您的两个条件之一,但您只想获得满足两个条件的条目。使用 AND 时的问题(这个答案似乎又被删除了)将是你不会得到任何行,因为游戏不能同时等于“国际象棋”和“跳棋”。 因此,这意味着您将需要两个查询并检查在这两个查询中都出现了哪些玩家,一个检查 game = "chess",一个检查 game="checker"。有不同的选择可以做到这一点。一种可能性是使用 IN 子句:

SELECT DISTINCT playerid
FROM daily_player
WHERE playerid IN (SELECT playerid FROM daily_player WHERE game = 'chess')
AND playerid IN (SELECT playerid FROM daily_player WHERE game = 'checkers')
AND website='abc.com';

另一种方法是使用 EXISTS:

SELECT DISTINCT playerid
FROM daily_player d1
WHERE EXISTS (SELECT 1 FROM daily_player WHERE game = 'chess' AND playerid = d1.playerid)
AND EXISTS (SELECT 1 FROM daily_player WHERE game = 'checkers' AND playerid = d1.playerid) 
AND website='abc.com'

请注意,您想要的“a1 b2”结果只有在使用 DISTINCT 而不是 select 游戏等不同列时才能实现。 如果你还想select他们,你当然可以这样做:

SELECT DISTINCT playerid,game,website
FROM daily_player
WHERE playerid IN (SELECT playerid FROM daily_player WHERE game = 'chess')
AND playerid IN (SELECT playerid FROM daily_player WHERE game = 'checkers')
AND website='abc.com';

但是你不会得到你显示的结果,但在这种情况下是四行而不是两行。如果你删除上面 select 的游戏,你会再次得到两行,因为网站没有区别。

我通常通过 "HAVING ".

在列中找到重复项

如果你只有两个游戏,这是最短的方法。

SELECT playerid
FROM daily_player
GROUP BY playerid 
HAVING COUNT(playerid ) > 1;    

如果您不想要很长的查询,可以使用连接函数。类似于:

create table chess as select * from daily_player where game = 'chess';
create table checkers as select * from daily_player where game = 'checkers';

select chess.playerid from chess inner join checkers
on chess.playerid = checkers.playerid;

一个带有多个子查询的长查询可能就可以了。

SELECT playerid FROM daily_player a
WHERE 
(SELECT COUNT(*) FROM daily_player WHERE game ='chess' AND playerid=a.`playerid`)=1 
AND
(SELECT COUNT(*) FROM daily_player WHERE game ='checkers' AND playerid=a.`playerid`)=1
AND website='www.abc.com'
GROUP BY playerid;

结果

playerid  
----------
a1        
b2 

解释:

  1. 1st Subquery : 评估玩家是否下了游戏棋。
  2. 第二个子查询:评估玩家是否玩过跳棋。
  3. 使用AND检查两个子查询是否都是TRUE
  4. 再添加一个 AND 来评估网站。

注意:如果每个玩家都可以多次玩一个游戏,您可以将=1替换为>=1

如果您想获取同时下过国际象棋和西洋跳棋的 playerid,则查询将是:

SELECT playerid
FROM daily_player
WHERE game in ('checkers', 'chess') && website = 'www.abc.com' GROUP by playerid HAVING COUNT(*)=2;