|
楼主 |
发表于 2021-2-5 23:35
|
显示全部楼层
自己查了些资料,对这个问题有所理解,自问自答吧:
这个问题来源于access查询向导生成的重复项查询,当时看不明白,几年前就在这里发过帖询问,没有答复。最近又捡起access,还是对这个问题绕不过去。又通过SQL查询语句的角度提问,还是没有满意的答复。可能是问题太初级,解释起来又费劲吧。我在网上搜索,通过“access重复性查询”搜到了一篇文章,里面提到access重复性查询向导生成的SQL语句不容易理解,另外给出了用INNER JOIN方式的SQL查询,容易看懂。文章链接如下:
https://blog.csdn.net/gracexu/article/details/2134309
该文章没有直接对access生成的SQL语句进行解读,但提到了之所以不易理解,是因为涉及到了“子查询”。所以我又看了些有关“SQL子查询”的内容。终于在一定程度上理解了。下面是我的理解:
查询1是access生成的SQL语句:SELECT Contacts.FirstName, Contacts.LastName
FROM Contacts
WHERE (((Contacts.FirstName) In (SELECT [FirstName] FROM [Contacts] As Tmp GROUP BY [FirstName],[LastName] HAVING Count(*)>1 And [LastName] = [Contacts].[LastName])))
ORDER BY Contacts.FirstName, Contacts.LastName;
之前我不理解,是因为对“SQL关联子查询”的运行方式不了解。按照初级的编程语言的理解,我想当然的以为这条SQL语句应该先运行IN()里面的内容,返回结果用于上层Where()语句,最后再把返回结果应用于最外层的select语句。这样去理解,会遇到无法解决的困惑。
而“SQL关联子查询”真正的运行方式是这样的:外层先把查询结果每次输送一条给子查询。这个例子里,外层查询出的是全部记录,首先把第一条记录(Annie,matter)传输给子查询,此时的子查询中,SELECT [FirstName] FROM [Contacts] As Tmp GROUP BY [FirstName],[LastName] HAVING Count(*)>1 And [LastName] = [Contacts].[LastName]语句首先有了限定条件:[LastName]=“matter”,又对[FirstName],[LastName]进行聚合,实际上的结果只有“Annie”这一条记录。这个结果输送给上一层,相当于WHERE “Annie” In {"Annie"},语句成立,外层查询SELECT Contacts.FirstName, Contacts.LastName
FROM Contacts成功输出了第一条查询结果(Annie,matter)。
然后第二条记录、第三条记录……依次执行。当遇到(pete,teeth)这条记录时,子查询SELECT [FirstName] FROM [Contacts] As Tmp GROUP BY [FirstName],[LastName] HAVING Count(*)>1 And [LastName] = "teeth"由于聚合的结果不大于1,返回的结果是空。所以对外层查询来说,(pete,teeth)这条记录就被排除了。
查询2是我改的,把子查询中我当初理解不了的And [LastName] = [Contacts].[LastName]去掉了。
SELECT Contacts.FirstName, Contacts.LastName
FROM Contacts
WHERE (((Contacts.FirstName) In (SELECT [FirstName] FROM [Contacts] As Tmp GROUP BY [FirstName],[LastName] HAVING Count(*)>1 )))
ORDER BY Contacts.FirstName, Contacts.LastName;
这样一来,子查询和外层查询的关联就没有了。我不清楚整个SQL语句运行时是否还是每次由外层传递给子查询一条记录。不管如何,此时当遇到(pete,teeth)这条记录时,查询SELECT [FirstName] FROM [Contacts] As Tmp GROUP BY [FirstName],[LastName] HAVING Count(*)>1因为少了一个限制,聚合后返回给上层的结果应该是{Annie,Pete,Sue}而不再是空。所以就错误的输出了(pete,teeth)这条查询结果。 |
|