子查询一直都是错误的,我该怎么办?

时间:2019-06-06 20:24:11

标签: mysql sql

所以对于体育赛事系统,我具有以下表结构

团队表
team_id
game_id
team_name
team_logo

玩家桌 player_id
team_id
player_name
player_mobile
player_email

因此,只要球员提交了球队注册信息,就会在两个表中都保存该信息。事件可能是诸如板球,篮球,无挡板篮球等。有时他们不填写球员的详细信息,有时又重新提交球队,这意味着要提交相同的球队名称。

因此,每当我需要检查团队列表的准确详细信息时,我就一直在使用以下代码:

SELECT team_id FROM `teams` WHERE `game_id`= 35 GROUP BY `team_name

要获取这些团队中与我使用的同名人员的列表:

SELECT team_id, player_name FROM `player` WHERE team_id IN (SELECT team_id FROM `teams` WHERE `game_id`= 35 GROUP BY `team_name`) AND player_name IS NOT NULL AND player_name <> ''

问题是顶部的查询给我的结果与底部的查询不同。我需要做的是随时获取当前团队的列表。团队副本不应存在。然后,我需要这些球队的球员名单。

目前很沮丧:(请帮我。

2 个答案:

答案 0 :(得分:0)

Select t.team_id , p.player_name from player p
JOIN teams t 
ON t.team_id = p.team_id
Where t.game_id = 35 AND p.player_name IS NOT NULL AND p.player_name <> ''
GROUP BY(t.team_name)
```

You should do a unique constraint on the team_name column, this way you are not allowing duplicate teams

Ps. I did not test the query but it should work

答案 1 :(得分:0)

TL; DR

使用JOINDISTINCT

可获得所需的结果。
SELECT DISTINCT t.team_name, P.player_name 
FROM teams AS t
    INNER JOIN Players AS p
        ON p.team_id = t.team_id;

完整说明

以下查询不是确定性的,也就是说,您可以对同一数据多次运行同一查询并获得不同的结果:

SELECT team_id 
FROM `teams` 
WHERE `game_id`= 35 
GROUP BY `team_name`;

许多DBMS甚至都不允许运行此查询。您已声明某些团队重复,因此请考虑以下虚拟数据:

team_id    team_name     game_id
------------------------------------
   1       The A-Team       35
   2       The A-Team       35
   3       The A-Team       35

当您按team_name分组时,您将分组,所以如果我们以有效的查询开头:

SELECT team_name
FROM `teams` 
WHERE `game_id`= 35 
GROUP BY `team_name`;

我们希望得到一个结果:

team_name
--------------
The A-Team

team_id添加到选择中时,没有聚合功能,则需要为team_id选择一个值,但是查询引擎有3个不同的值可供选择,但没有一个比其他任何一个都正确。这就是为什么必须将select语句中的任何内容包含在组中(或在功能上依赖于所包含的内容)或聚合函数的一部分。

MySQL Docs状态:


  

在标准SQL中,包含GROUP BY子句的查询不能引用选择列表中未在GROUP BY子句中命名的未聚合列。例如,此查询在标准SQL中是非法的,因为选择列表中的名称列未出现在GROUP BY中:

SELECT o.custid, c.name, MAX(o.payment)
  FROM orders AS o, customers AS c
  WHERE o.custid = c.custid
  GROUP BY o.custid;
  

为使查询合法,必须从选择列表中省略名称列或在GROUP BY子句中命名。

     

MySQL扩展了GROUP BY的使用,以便选择列表可以引用未在GROUP BY子句中命名的非聚合列。这意味着前面的查询在MySQL中是合法的。您可以使用此功能来避免不必要的列排序和分组,从而获得更好的性能。但是,这主要在每个未聚合列中未在GROUP BY中命名的所有值对于每个组都相同时才有用。

此子句存在的原因是有效的,并且可以节省一些时间,请考虑以下查询:

SELECT t.team_id, t.team_name, COUNT(*) AS Players
FROM teams AS t
    LEFT JOIN Players AS p
        ON p.team_id = t.team_id
GROUP BY t.team_id;

在这里,我们可以将team_name包括在选择列表中,即使它不在分组依据中,但是由于team_id是主键,因此我们可以安全地进行此操作,因此不可能单个team_name具有两个不同的team_id值。

无论如何,我离题了,您最有可能遇到的问题是,根据查询的上下文和所选的执行计划,每个查询中为team_id返回的值可能会有所不同。

您可以使用DISTINCT获得球员和球队的不同列表:

SELECT DISTINCT t.team_name, P.player_name 
FROM teams AS t
    INNER JOIN Players AS p
        ON p.team_id = t.team_id;

从本质上讲,这是一种黑客行为,尽管它确实删除了重复记录,但不能解决根本问题,重复记录以及潜在的次优数据结构。

如果还不算太晚,我将重新考虑您的设计并进行一些更改。如果团队名称应该是唯一的,则请使用唯一的约束条件使其具有唯一性,因此不必完全解决重复的条目,而可以完全避免。

您可能应该将联结表用于玩家和游戏,即拥有主表

Team (team_id, team_name, team_logo etc)
Game (game_id, game_name, etc)
Player (player_id, player_name, player_email, player_mobile etc)

然后用表格链接它们

Team_Game (team_id, game_id)
Team_Player (team_id, player_id)

然后,这将允许一个球员为多个团队效力,或者一个团队输入多个事件。