下面的SQL查询获取具有不同姓氏的所有first_names。
select a.first_name
from names a
WHERE a.first_name in (
select b.first_name
from names b
WHERE a.last_name<>b.last_name
)
我无法弄清楚这究竟是如何工作的。我认为会发生的情况是,对于表中的每一行,子查询将检查是否存在具有不同姓氏的行。但是检查仅在相同的名字值之间进行。有人可以解释一下这实际上是如何工作的。
首先,正如我在评论中提到的,我建议为此使用HAVING
。它不需要对表进行 2 次扫描,只需要一次,它不会返回相同first_name
的重复项,并且您可能更容易理解:
SELECT first_name
FROM dbo.names
GROUP BY first_name
HAVING COUNT(DISTINCT last_name) > 1;
这应该是相当不言自明的;它返回的行中,每个值last_name
first_name
都有超过 1 个不同的值。
对于您的查询,让我们看看WHERE
:
WHERE a.first_name IN (SELECT b.first_name
FROM names b
WHERE a.last_name<>b.last_name
首先,我们"连接"names
的 2 个实例(别名a
adb
),其中last_name
的值在 2 个实例中不同。这很可能是一项昂贵的操作;如果你有一个表将有 1,000 行,并且它有 900 个不同的值last_name
那么你最终会得到联接每行数百个匹配项。
之后,它检查在联接的行集中别名为a
的实例中的行first_name
值names
;然后有 2 个(或更多)具有不同last_name
值的相同first_name
实例。
在上下文中,将IN
与使用值的文本列表没有什么不同。 如果表中I
列SomeTable
具有值1
、2
、3
、4
、5
和7
,则WHERE SomeColumn IN (1,2,3,4,5,7)
与WHERE SomeColumn IN (SELECT I FROM SomeTable)
相同。
你可以像这样将其解读为内部连接,或者 EXISTS :
SQL 小提琴
查询 2:
select a.first_name
from names a
inner join names b
on a.first_name = b.first_name
and a.last_name <> b.last_name
Group by a.first_name, a.last_name
结果:
| first_name |
|------------|
| john |
| john |
| john |
查询 3:
select a.first_name
from names a
where exists(
select 1 from names b
WHERE a.first_name = b.first_name
and a.last_name <> b.last_name
)
结果:
| first_name |
|------------|
| john |
| john |
| john |
- 首先进行语法检查,然后创建表达式树(此时您可以另外检查项目和"排列")(即表中确实存在字段)。这是初始阶段;如果有错误,你只是建议提交者认真对待。
- 然后是分析。SQL 查询与程序的不同之处在于它不指定如何执行任务;相反,它指定结果是什么。基于集合的逻辑。因此,您引入了一个查询分析器(根据产品的不同,从糟糕到好 - Oracle 长期以来一直使用糟糕的查询分析器,DB2 具有最敏感的查询分析器,包括监视磁盘速度)来找出如何最好地处理此结果。这是一个非常复杂的野兽,它可能会尝试数十种或数百种技术,然后才能确定他认为最快的一种(基于成本,基本上是一些统计数据)。
- 然后执行。