【问题标题】:How does SQL count(distinct) work in this case?SQL count(distinct) 在这种情况下如何工作?
【发布时间】:2021-08-31 15:28:04
【问题描述】:

我正在尝试查找德国对阵波兰的比赛编号。这是来自https://www.w3resource.com/sql-exercises/soccer-database-exercise/sql-subqueries-exercise-soccer-database-4.php。有两个表:match_details 和 football_country。我不明白在这种情况下 count(distinct) 是如何工作的。有人可以澄清一下吗?谢谢!

SELECT match_no 
FROM match_details 
WHERE team_id = (
    SELECT country_id 
    FROM soccer_country 
    WHERE country_name = 'Germany') 
  OR team_id = (
    SELECT country_id 
    FROM soccer_country 
    WHERE country_name = 'Poland') 
GROUP BY match_no 
HAVING COUNT(DISTINCT team_id) = 2;

【问题讨论】:

  • 天哪,这是一种复杂的方式。无论如何,由于每场比赛显示两次(每个球队/国家一次),HAVING COUNT(DISTINCT team_id) = 2 只是检查结果是否显示一场比赛
  • 嘿 Lamak,对不起,我还是不明白。所以,count(distinct team_id) 将检查每个 match_no 的不同 team_id 对吗?但那不是每个 match_no 的情况吗?由于每个 team_id 都是不同的...

标签: sql count


【解决方案1】:

正如 Lamak 所提到的,查询的考虑是多么丑陋,但处理查询的方法有很多。

如前所述,计算 (Distinct team_id) 可确保只有 2 个独特的团队。如果存在笛卡尔结果,您可能会重复多行,显示两个团队的多个实例。所以 TEAM_ID 上的不同计数消除了这一点。

现在,也就是说,我看到的其他“团队”查询数据结构有一条比赛记录和每支球队参加比赛的列。从长远来看,这更容易,但仍然是一个相对容易的查询。

稍微分解查询,并考虑一个大规模的数据集(并不是说这个,或者任何类型的甚至是职业联赛都会有如此大的记录计数,从而给 SQL 引擎带来延迟)。

您的第一个标准是与德国的比赛。所以让我们开始吧。

SELECT 
      md1.match_no 
   FROM 
      match_details md1
         JOIN soccer_country sc1
            on md1.team_id = sc1.country_id
            AND sc1.country_name = 'Germany'

那么,如果德国甚至不是双方比赛的一部分,为什么还要查看任何其他记录/比赛。其中这本身将从 51 个匹配的样本数据中返回 6 个匹配。所以现在,您需要做的就是再次将这些比赛加入到比赛详细信息表中,但第二支球队也是波兰

SELECT 
      md1.match_no 
   FROM 
      match_details md1
         JOIN soccer_country sc1
            on md1.team_id = sc1.country_id
            AND sc1.country_name = 'Germany'
         -- joining again for the same match Germany was already qualified
         JOIN match_details md2
            on md1.match_no = md2.match_no
            -- but we want the OTHER team record since Germany was first team
            and md1.team_id != md2.team_id
            -- and on to the second country table based on the SECOND team ID
            JOIN soccer_country sc2
               on md2.team_id = sc2.country_id
               -- and the second team was Poland
               AND sc2.country_name = 'Poland'

是的,可能是一个更长的查询,但是通过消除 45 个其他匹配项(再次考虑一个大型数据库),您已经将大量数据保存到一个非常有限的集合中。而现在只整理那些德国/波兰。没有聚合、计数、不同,只有直接连接。

反馈

让我们来看看一些 BAD 示例数据......正如所有程序员都知道的那样,没有这样的事情 (NOT)。总之,让我们来看看这几场比赛。

Match    Team ID    blah
52       Poland     Just put the names here for simplistic purposes
52       Poland
53       Germany
53       Germany

如果您要在没有 DISTINCT Teams 的情况下运行查询,则第 52 场和第 53 场比赛都会出现...因为波兰是一支球队,在第 52 场比赛中出现 2 次,同样,德国在第 53 场比赛中出现 2 次。通过执行 DISTINCT球队,您可以看到每场比赛只有 1 支球队被退回,因此被排除在外。这有帮助吗?同样,没有坏数据之类的东西:)

还有超过 2 个团队创建的另一个示例比赛

Match    Team ID    
54       France     
54       Poland
54       England
55       Hungary
56       Austria

在每个匹配项中,都将返回 NONE。第 54 场比赛有 3 支不同的球队,第 55 场和第 56 场比赛只有单场比赛,因此没有对手可竞争。

第二次反馈

澄清查询。如果您查看仅针对德国的简短查询,则“md1”的别名实例已经位于德国匹配的任何给定记录中。所以第二次加入“md2”,我只关心同一个匹配,所以我可以加入同一个match_no。但是,在“md2”别名中,“!=”表示不等于。 ! = 逻辑非。所以加入是说从 MD1,加入到相同匹配 id 上的 MD2 别名。但是,只在团队不一样的地方给我。所以第一个实例拥有德国的团队 ID(已经合格),因此给了我第二个团队 ID。因此,现在我可以使用辅助 (md2) 实例团队 ID 加入该国家/地区,以确认仅适用于波兰。

现在这是否为您澄清了一些事情?

【讨论】:

  • 嘿 DRapp..谢谢您的回复。但是我们可以回到这个:“计算 (Distinct team_id) 确保只有 2 个独特的团队。”如果我们按 match_no 分组并且已经为 team_id 指定了德国和波兰(来自我的代码),那么结果只会是唯一的match_no,对吗?计算不同的 team_id 与它有什么关系?
  • @rahul,请参阅带有 DISTINCT 说明的修订答案。
  • 嘿 DRapp,感谢您的澄清。还有一个问题:在您的代码中,您专门使用连接,您能否解释为什么必须创建 md2?SELECT md1.match_no FROM match_details md1 JOIN football_country sc1 on md1.team_id = sc1.country_id AND sc1.country_name = 'Germany'和“波兰”。会,它不会像这样工作吗?另外,为什么你必须加入 md1 和 md2? '!' 的功能是什么?操作员?对不起,我只是一个初学者,所以有很多疑问......
  • @rahul,再次为您修改答案。
  • 嘿,DRapp,是的,这就解释了。非常感谢!
猜你喜欢
  • 2020-10-30
  • 2021-07-18
  • 1970-01-01
  • 1970-01-01
  • 2021-05-25
  • 1970-01-01
  • 2013-11-14
  • 1970-01-01
  • 2018-06-16
相关资源
最近更新 更多