记录的动力总是来自于工作中遇到的问题。上次只要根据某个字段把有重复项的记录列出来,这次条件增多了,要根据两个或两个以上字段来判断,当这些字段的值全部相同时,才认为出现了重复记录。
还是以上次的数据为例吧,略有修改。表名 Student
ID | Name | City | Address |
1 | 徐俊 | 北京 | 北京市东四北大街520号 |
2 | 王洪涛 | 北京 | 北京市西单北大街151号 |
3 | 张立涛 | 大连 | 大连市西岗区新开路69号 |
4 | 佘高峰 | 济南 | 山东省济南市泺文路50号 |
5 | 徐俊 | 上海 | 上海市静安区南阳路46号 |
6 | 张忠飞 | 上海 | 上海市肇嘉浜路414号 |
7 | 徐俊 | 上海 | 上海市乳山路150号 |
从城市角度看,一个城市有很多学员很正常;中国人重名的多,单看名字很难说是不是同一个人。这次我们的查询要结合“City”和“Name”两个字段,只有这两个字段的值都相等,我们才进一步检查是不是同一个人。
先用Access 2003 提供的“查找重复项查询向导”生成一个查询看看:
SELECT student.Name, student.City, student.Address
FROM student
WHERE ((student.Name) In (SELECT [Name] FROM [student] As Tmp GROUP BY [Name], [City] HAVING Count(*)>1 And [City] = [student].[city]))
ORDER BY student.Name, student.City
结果是:
Name | City | Address |
---|---|---|
徐俊 | 上海 | 上海市乳山路150号 |
徐俊 | 上海 | 上海市静安区南阳路46号 |
注意: 徐俊 北京 没有列出来,符合我们的预期,因为我们这次是两个标准。
不过我觉得Access 的向导生成的语句有点搞,看上去不是那么一目了然。
这条SQL语句依然用了子查询“select name from student group by name, city having count(*)>1”。这个子查询的意思是:把student表里的记录同时按名字和城市组合在一起,并把组合后数量大于1的记录返回。就这个例子而言,这条子查询的返回值是“徐俊/上海”。
但是跟单个字段查找重复值不一样的地方是,这次多了个“And [City] = [student].[city]”,我们这次的子查询的全部内容是:
select name from student as Tmp group by name, city having count(*)>1 And [City] = [student].[city]
这个子查询有外部条件,这就让事情有点复杂了。在子查询里使用外部条件,需要对SQL 语句使用的相当熟练和有技巧。
我换了种SQL的写法来达到同样效果,自己觉得看上去清晰点。
SELECT student.Name, student.City, student.Address
FROM student inner join
(SELECT Name, city FROM student GROUP BY Name, City HAVING Count(*)>1 ) As Tmp
ON student.Name=Tmp.Name AND student.city = Tmp.city
ORDER BY student.Name, student.City