2

Teams在这种情况下,我有 3 个表: PlayersPlayersInTeams

APlayer只是一个注册用户。没有 W/L 数据与Player.

ATeam维护赢/输记录。如果一个玩家是自己玩,那么他会和他的“单人”团队一起玩(Team只有那个玩家在里面)。每次 Bob 和 Jan 一起获胜时,他们的Team参赛作品都会获得胜利++。每次 Jason 和 Tommy 一起输掉比赛时,他们的 Team entry 都会输掉++。

PlayersInTeams表只有 2 列,它是 和 之间的交集PlayersTeams

> desc PlayersInTeams ;
+------------+---------+
| Field      | Type    |
+------------+---------+
| fkPlayerId | int(11) |
| fkTeamId   | int(11) |
+------------+---------+

所以这是困难的部分:

因为 aPlayer可以是 multiple 的一部分,所以在匹配开始时从表中Teams获取权限很重要。TeamIdTeams

玩家的 SOLO 团队由

select fkTeamId from PlayersInTeams where
fkPlayerId=1 HAVING count(fkTeamId)=1;

不,这不对!!但我不明白为什么。

我想说:


fkPlayerId=1 的 PlayersInTeams 中获取 fkTeamId,而且
具有此特定 fkTeamId 的行数正好为 1。

查询返回(空集),实际上如果我将 HAVING 子句更改为不正确(HAVING count(fkTeamId)<>1;),它会返回我想要的行。

4

5 回答 5

3

要修复您的查询,请添加一个group by. 要计算每个团队的计数,您需要更改where子句以返回玩家 1 所在的所有团队:

select  fkTeamId 
from    PlayersInTeams 
where   fkTeamId in
        (
        select  fkTeamId
        from    PlayersInTeams
        where   fkPlayerId = 1 
        )
group by
        fkTeamId
having  count(*) = 1;

SQL Fiddle 的示例。


下面详细解释了为什么您的count(*) = 1病情会以令人惊讶的方式起作用。当查询包含聚合 like count,但没​​有group by子句时,数据库会将整个结果集视为一个组。

group by在 MySQL 以外的数据库中,如果没有聚合,则无法选择不在 a 中的列。在 MySQL 中,所有这些列都与数据库遇到的第一个值一起返回(本质上是组中的随机值。)

例如:

create table YourTable (player int, team int);
insert YourTable values (1,1), (1,2), (2,2);

select  player
,       team
,       count(team)
from    YourTable
where   player = 2

-->

player   team    count(team)
1        1       1

前两列来自随机行player = 1。该count(team)值为 2,因为有两行player = 1和一个非 null team。计数没有说明球队中的球员人数。

于 2013-06-01T22:24:08.947 回答
2

最自然的做法是计算行数以查看发生了什么:

select fkTeamId, count(*)
from PlayersInTeams
where fkPlayerId=1
group by fkTeamId;

group by子句是编写查询的更自然的方式:

select fkTeamId
from PlayersInTeams
where fkPlayerId=1
having count(fkteamid) = 1

但是,如果玩家只有一行,那么您的原始版本应该可以工作 - 过滤会将其带到一行, fkTeamId 将是该行的团队并且having会满意。一种可能性是数据中有重复的行。

如果重复是一个问题,您可以这样做:

select fkTeamId
from PlayersInTeams
where fkPlayerId=1
having count(distinct fkteamid) = 1

编辑“单人团队”:

正如 Andomar 所指出的,人团队的定义并不完全符合我的预期。它是一名球员,是球队中唯一的球员。因此,要获取给定球员所在球队的球队名单:

select fkTeamId
from PlayersInTeams
group by fkTeamId
having sum(fkPlayerId <> 1) = 0

也就是说,您无法过滤掉其他玩家并期望获得此信息。您特别需要他们,以确保他们不在团队中。

如果您想获得所有单人团队:

select fkTeamId
from PlayersInTeams
group by fkTeamId
having count(*) = 1
于 2013-06-01T22:24:29.333 回答
1

SqlFiddle在这里:http ://sqlfiddle.com/#!2/36530/21

尝试先找到有一名球员的球队,然后使用它来查找球员 ID(如果他们在任何球队中):

select DISTINCT PlayersInTeams.fkTeamId
from (
  select fkTeamId 
  from PlayersInTeams
  GROUP BY fkTeamId
  HAVING count(fkPlayerId)=1
) AS Sub
INNER JOIN PlayersInTeams
  ON PlayersInTeams.fkTeamId = Sub.fkTeamId
WHERE PlayersInTeams.fkPlayerId = 1;
于 2013-06-01T22:34:41.767 回答
1

HAVING通常与GROUP BY语句一起使用 - 它就像WHERE应用于分组数据的 a。

SELECT fkTeamId
FROM PlayersInTeams
WHERE fkPlayerId = 1
GROUP BY fkTeamId
HAVING COUNT(fkPlayerId) = 1
于 2013-06-01T22:24:27.350 回答
0

这里每个人的回答都非常有帮助。除了丢失之外GROUP BY,我发现我的问题主要是我的WHERE条款“太早了”。

说我们有

insert into PlayersInTeams values
  (1, 1), -- player 1 is in solo team id=1
  (1, 2),(2,2) -- player 1&2 are on duo team id=2
;

现在我们尝试:

select fkTeamId from PlayersInTeams
where fkPlayerId=1 -- X kills off data we need
group by fkTeamId
HAVING count(fkTeamId)=1;

特别WHERE是过滤临时结果集,以便从结果集中删除任何没有的行。 fkPlayerId=1由于每个 fkPlayerId 只与每个 fkTeamId 关联一次,当然 fkTeamId 出现次数的 COUNT 始终为 1。所以你总是会得到一个球员 1所属球队的列表,但你仍然不知道他的SOLO团队。

戈登对我的附录的回答

select fkPlayerId,fkTeamId
from PlayersInTeams
group by fkTeamId
having count(fkTeamId) = 1
and fkPlayerId=1 ;

特别好,因为它是一个便宜的查询并且可以满足我们的需求。它首先选择所有 SOLO 团队,(选择所有在表中仅出现一次的 fkTeamIds(通过HAVING count(*)=1)),然后从那里我们说,“好的,现在给我这个 fkPlayerId=1 的那个”。瞧,独奏团队。

DUO 团队更难,但相似。困难与上述问题相似,只是 3 人团队和 2 人团队存在歧义。 SQL Fiddle 中的详细信息

于 2013-06-02T15:48:11.497 回答