学习笔记:LeetCode182:Duplicate Emails 以及MySQL中Group by的使用问题

  LeetCode182:Duplicate Emails

 

  Write a SQL query to find all duplicate emails in a table named Person.

   +----+---------+
  | Id | Email   |
  +----+---------+
  | 1  | a@b.com |
  | 2  | c@d.com |
  | 3  | a@b.com |
  +----+---------+

 

  For example, your query should return the following for the above table:

  +---------+
  | Email   |
  +---------+
  | a@b.com |
  +---------+

 

  一道简单的SQL题目,得到重复的Email数据。

 

  起先的想法很天真,

  1、借用group by去除重复的Email数据:

  SELECT Id FROM Person GROUP BY Email; 

  2、然后通过得到的Id过滤掉原表的数据:

  SELECT DISTINCT Email FROM Person WHERE Id NOT IN (SELECT Id FROM Person GROUP BY Email);                

 

  点提交,然后:Time Limit Exceeded......

 

  事实上第一句 SELECT Id FROM Person GROUP BY Email 的语法就是错误的,只是MYSQL支持了这一种反逻辑的写法。

 


  GROUP BY

  在W3里给出的含义是:

  GROUP BY 语句用于结合聚集函数,根据一个或多个列对结果集进行分组

  通常用法是:

  SELECT Name,COUNT(Salary) FROM Employee GROUP BY Name;


 

  而GROUP BY在MYSQL中的逻辑是:

  SELECT的返回字段,如果不在GROUP BY中,也不是聚集函数,那么字段的取值是从匹配的记录中随机取的;

  在做表关联统计的时候,可以简化GROUP BY后面的字段,只需要GROUP BY parent.Id 就可以了,而不用把 parent 的所有字段都列出来。

  举个例子:

  SELECT Parent.*, COUNT(Item.Id) AS Item_count FROM Parent LEFT JOIN Item ON Parent.Id = Item.Parent_Id GROUP BY Parent.Id;

 

  这种写法确实可以让SQL书写简化,其他的标准数据库中如果要实现同样的功能就必须用嵌套来实现:内部SQL用GROUP BY来返回Id字段,然后用返回的Id字段去关联表实现其他详细字段的输出。

  但还是不推荐MySQL的这种使用方法,虽然方便,但违反了SQL约定的逻辑:有GROUP BY的输出字段要么是聚集函数,要么是在GROUP BY中。

 

  最后给出此题的正确解法,采用INNER JOIN,过滤条件是两条数据的Email值相等但Id不相等。

  SELECT DISTINCT p.Email FROM Person p INNER JOIN Person q ON p.Id != q.Id AND p.Email = q.Email;

  或者

  SELECT DISTINCT p.Email FROM Person p,Person q WHERE p.Id != q.Id AND p.Email = q.Email; 
posted @ 2016-09-08 19:12  随行随念  阅读(202)  评论(0编辑  收藏  举报