请求解释获取存在不同姓氏的first_name的SQL查询执行逻辑
拆解你的SQL查询逻辑
首先要明确:这是一个相关子查询——子查询里用到了外层查询的a.last_name,所以它不是一次性跑完所有数据,而是跟着外层的每一行数据“联动”执行的。咱们一步步看执行过程:
- 外层遍历每一行数据:数据库会逐个取出
names表中的每一行,我们暂时叫它「行a」,它包含a.first_name(名字)和a.last_name(姓氏)。 - 针对每行a执行子查询:此时子查询的任务是:从
names表中找出所有姓氏和行a不一样的行(叫它们「行b」),然后把这些行b的first_name全部收集起来,形成一个名字集合。 - 外层判断是否符合条件:接下来检查「行a的first_name」是否在刚才子查询得到的名字集合里:
- 如果存在:说明至少有一个行b,它的姓氏和a不同,但名字和a完全相同——换句话说,这个名字对应的姓氏不止一种。
- 如果不存在:说明所有和a姓氏不同的行,名字都和a不一样,也就是这个名字只对应唯一的姓氏。
举个具体的例子,假设你的names表有这些数据:
| first_name | last_name |
|---|---|
| John | Doe |
| John | Smith |
| Jane | Doe |
| Bob | Brown |
- 当外层取到「John Doe」这行时,子查询会找出所有姓氏不是Doe的行(也就是John Smith、Bob Brown),收集它们的名字得到
['John', 'Bob']。此时John在这个集合里,所以这行会被选中。 - 当外层取到「John Smith」这行时,子查询找出姓氏不是Smith的行(John Doe、Jane Doe、Bob Brown),名字集合是
['John', 'Jane', 'Bob'],John在里面,所以也被选中。 - 当外层取到「Jane Doe」时,子查询找出姓氏不是Doe的行(John Smith、Bob Brown),名字集合是
['John', 'Bob'],Jane不在里面,所以不会被选中。 - 当外层取到「Bob Brown」时,子查询找出姓氏不是Brown的行(John Doe、John Smith、Jane Doe),名字集合是
['John', 'John', 'Jane'],Bob不在里面,也不会被选中。
最终查询结果就是John、John——也就是所有对应多种姓氏的名字的行。
如果想更直观地实现同样的效果,可以用分组查询的写法,可读性更强:
-- 只返回符合条件的名字(去重) SELECT first_name FROM names GROUP BY first_name HAVING COUNT(DISTINCT last_name) > 1;
或者要返回所有符合条件的行(包括重复的名字):
SELECT n.first_name FROM names n JOIN ( SELECT first_name FROM names GROUP BY first_name HAVING COUNT(DISTINCT last_name) > 1 ) AS name_with_multiple_last_names ON n.first_name = name_with_multiple_last_names.first_name;
内容的提问来源于stack exchange,提问作者ArunJose
相关产品推荐
相关产品推荐

