资讯动态

SQL去重:为什么加了DISTINCT,同一所学校还是出现多次?

发布时间:2026/10/6 1:50:55 来源:尧图企业网站定制
原来的题目很短运营想知道用户来自哪些学校从用户表里取出学校的去重数据。牛客原题查询结果去重。答案只有一行SELECT DISTINCT university FROM user_profile;但会写这行不代表已经理解去重。比如再加一列用户编号为什么同一所学校又出现了这不是 DISTINCT 失效而是我们改变了“什么算重复”。1. 先看一张只有必要字段的表下面是独立实验表不需要使用或修改已有的 user_profile。请在自己的练习数据库中执行表名已存在时换一个名字。CREATE TABLE sql3_distinct_demo ( id INT NOT NULL PRIMARY KEY, university VARCHAR(32), province VARCHAR(32) NOT NULL ); INSERT INTO sql3_distinct_demo VALUES (1, 北京大学, 北京), (2, 北京大学, 北京), (3, 复旦大学, 上海), (4, 复旦大学, 其他), (5, NULL, 北京), (6, NULL, 上海);iduniversityprovince1北京大学北京2北京大学北京3复旦大学上海4复旦大学其他5NULL北京6NULL上海为了观察 NULL这里允许学校为空原题学校列是 NOT NULL原题答案并不依赖这些扩展行。2. 单列去重我们只关心学校SELECT DISTINCT university FROM sql3_distinct_demo;结果集合是三项北京大学、复旦大学、NULL。这里不列固定的先后顺序因为 SQL 没有 ORDER BY 时不能依赖返回顺序。可以把这个小例子想成先取出需要的列 再判断结果行是否重复 北京大学 北京大学 北京大学 复旦大学 复旦大学 - 复旦大学 NULL NULL NULL这只是理解查询语义的画法不代表数据库一定先物化整张中间表再做一次扫描实际执行可能借助索引等方式。3. 多列去重相同学校不再等于相同结果行SELECT DISTINCT university, province FROM sql3_distinct_demo;结果集合变成五项universityprovince北京大学北京复旦大学上海复旦大学其他NULL北京NULL上海第 1、2 行的两列都相同合成一项。第 3、4 行学校一样但省份不同所以必须保留两项。DISTINCT 不是只修饰紧跟在它后面的第一列而是对整个选出的结果行去重。MySQL 官方也给出了多列 DISTINCT 与按这些列 GROUP BY 的对应例子。官方说明。所以这句也不会得到“一所学校只留一个用户”SELECT DISTINCT id, university FROM sql3_distinct_demo;它仍然返回六行id 每行不同整个二元组就没有重复。4. 去重不是删除也不是挑一个代表上面的查询不会删掉表里的第 2 行也不会把第 4 行的学校改掉。SELECT COUNT(*) AS original_rows FROM sql3_distinct_demo;仍是 6。DISTINCT 改的是结果集合不是原始数据。如果需求是“一所学校挑一个用户”还必须说明挑谁最早注册的编号最小的最近活跃的只写 DISTINCT id, university 无法表达这些规则。原题只是取学校名单不需要引入这个额外问题。5. NULL 与排序两个小边界去重时两项 NULL 可以被合并这不意味着 WHERE university NULL 能筛出空学校。筛空值仍要用 IS NULL。MySQL 的 NULL 说明。如果业务只想要已知学校并且要一个明确的排序SELECT DISTINCT university FROM sql3_distinct_demo WHERE university IS NOT NULL ORDER BY university;这里 DISTINCT 负责去重WHERE 负责筛选ORDER BY 负责排序。中文具体先后受排序规则影响不能把“拼音排序”当默认承诺。字符是否相等也受 MySQL 的 collation 影响。本文用完全相同的中文字符串验证重复没有用 SQLite 的结果替代 MySQL 大小写、重音或尾空格行为。6. 我怎么验证这些解释本次在本地 SQLite 内存数据库执行上面的实验 SQL校验以下结果MySQL 语义另按官方文档核对。没有把它写成已经运行 MySQL 的截图也没有测性能。查询校验目标单列 DISTINCT3 项NULL 只出现一次两列 DISTINCT5 项不误删不同省份的复旦大学id 学校 DISTINCT6 项原表 COUNT(*)6 行查询没有删除记录排除 NULL 后去重2 所已知学校另外验证了空表、全部重复和全部 NULL。无排序的查询按集合核对不把某次碰巧返回的顺序写进断言。写 SQL 前我现在会先问一句我要去重的对象到底是一个字段的值还是几列组成的一整行这句话比记住 DISTINCT 的拼写更有用。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑