详述 SQL 中的 distinct 和 row_number() over() 的区别及用法
1 前言
在咱们编写 SQL 语句操作数据库中的数据的时候,有可能会遇到一些不太爽的问题,例如对于同一字段拥有相同名称的记录,我们只需要显示一条,但实际上数据库中可能含有多条拥有相同名称的记录,从而在检索的时候,显示多条记录,这就有违咱们的初衷啦!因此,为了避免这种情况的发生,咱们就需要进行“去重”处理啦,那么何为“去重”呢?说白了,就是对同一字段让拥有相同内容的记录只显示一条记录。
那么,如何实现“去重”的功能呢?对此,咱们有两种方式可以实现该功能。
- 第一种,在编写 select 语句的时候,添加 distinct 关键词;
- 第二种,在编写 select 语句的时候,调用 row_number() over() 函数。
以上两种方式都可以实现“去重”功能,那两者之间有何异同呢?接下来,作者将给出详细的说明。
2 distinct
在 SQL 中,关键字 distinct 用于返回唯一不同的值。其语法格式为:
SELECT DISTINCT 列名称 FROM 表名称
假设有一个表“CESHIDEMO”,包含两个字段,分别 NAME 和 AGE,具体格式如下:
观察以上的表,咱们会发现:拥有相同 NAME 的记录有两条,拥有相同 AGE 的记录有三条。如果咱们运行下面这条 SQL 语句,
/**
* 其中 PPPRDER 为 Schema 的名字,即表 CESHIDEMO 在 PPPRDER 中
*/
select name from PPPRDER.CESHIDEMO
将会得到如下结果:
观察该结果,咱们会发现在以上的四条记录中,包含两条 NAME 值相同的记录,即第 2 条记录和第 3 条记录的值都为“gavin”。那么,如果咱们想让拥有相同 NAME 的记录只显示一条该如何实现呢?这时,就需要用到 distinct 关键字啦!接下来,运行如下 SQL 语句,
select distinct name from PPPRDER.CESHIDEMO
将会得到如下结果:
观察该结果,显然咱们的要求得到实现啦!但是,咱们不禁会想到,如果将 distinct 关键字同时作用在两个字段上将会产生什么效果呢?既然想到了,咱们就试试呗,运行如下 SQL 语句,
select distinct name, age from PPPRDER.CESHIDEMO
得到的结果如下所示:
观察该结果,哎呀,貌似没有作用啊?她将全部的记录都显示出来了啊!其中 NAME 值相同的记录有两条,AGE 值相同的记录有三条,完全没有变化啊!但事实上,结果就应该是这样的。因为当 distinct 作用在多个字段的时候,她只会将所有字段值都相同的记录“去重”掉,显然咱们“可怜”的四条记录并不满足该条件,因此 distinct 会认为上面四条记录并不相同。空口无凭,接下来,咱们再向表“CESHIDEMO”中添加一条完全相同的记录,验证一下即可。添加一条记录后的表如下所示:
再运行如下的 SQL 语句,
select distinct name, age from PPPRDER.CESHIDEMO
得到的结果如下所示:
观察该结果,完美的验证了咱们上面的结论。
此外,有一点需要大家特别注意,即:关键字 distinct 只能放在 SQL 语句中所有字段的最前面才能起作用,如果放错位置,SQL 不会报错,但也不会起到任何效果。
3 row_number() over()
在 SQL Server 数据库中,为咱们提供了一个函数 row_number() 用于给数据库表中的记录进行标号,在使用的时候,其后还跟着一个函数 over(),而函数 over() 的作用是将表中的记录进行分组和排序。两者使用的语法为:
ROW_NUMBER() OVER(PARTITION BY COLUMN1 ORDER BY COLUMN2)
意为:将表中的记录按字段 COLUMN1进行分组,按字段 COLUMN2 进行排序,其中
- PARTITION BY:表示分组
- ORDER BY:表示排序
接下来,咱们还用表“CESHIDEMO”中的数据进行测试。首先,给出没有使用 row_number() over() 函数时查询的结果,如下所示:
然后,运行如下 SQL 语句,
select PPPRDER.CESHIDEMO.*, row_number() over(partition by age order by name desc) from PPPRDER.CESHIDEMO
得到的结果如下所示:
从上面的结果可以看出,其在原表的基础上,多了一列标有数字排序的列。那么反过来分析咱们运行的 SQL 语句,发现其确实按字段 AGE 的值进行分组了,也按字段 NAME 的值进行排序啦!因此,函数的功能得到了验证。
接下来,咱们就研究如何用 row_number() over() 函数实现“去重”的功能。通过观察上面的结果,咱们可以发现,如果以 NAME 分组,以 AGE 排序,然后再取每组的第一个记录或许就可以实现“去重”的功能啊!那么试试看,运行如下 SQL 语句,
/*
* 其中 rn 表示最后添加的那一列
*/
select * from
(select PPPRDER.CESHIDEMO.*, row_number() over(partition by name order by age desc) rn from PPPRDER.CESHIDEMO)
where rn = 1
运行后,得到的结果如下所示:
观察以上的结果,我们发现,哎呀,数据“去重”的功能一不小心就被咱们实现了啊!不过很遗憾,如果咱们细心的话,会发现一个很不爽的事情,那就是在执行以上 SQL 语句进行“去重”的时候,有一条 NAME 值为“gavin”、AGE 值为“18”的记录被过滤掉了,但是在现实生活会中,同名不同年龄的事情太正常了。
4 总结
通过阅读及实践以上内容,咱们已经知道了,无论是用关键字 distinct 还是用函数 row_number() over() 都可以实现数据“去重”的功能。但是在实现使用的过程中,咱们要特别注意两者的用法特点以及区别。
- 在使用关键字 distinct 的时候,咱们要知道其作用于单个字段和多个字段的时候是有区别的,作用于单个字段时,其“去重”的是表中所有该字段值重复的数据;作用于多个字段的时候,其“去重”的表中所有字段(即 distinct 具体作用的多个字段)值都相同的数据。
- 在使用函数 row_number() over() 的时候,其是按先分组排序后,再取出每组的第一条记录来进行“去重”的(在本篇博文中如此)。当然,在此处咱们还可以通过不同的限制条件来进行“去重”,具体如何实现,就需要大家自己去动脑思考啦!
结束语:在本篇博文中,作者详述了自己对用关键字 distinct 和函数 row_number() over() 进行数据“去重”的一些认识,希望以上的内容能够对大家有所帮助!
详述 SQL 中的 distinct 和 row_number() over() 的区别及用法的更多相关文章
- 述 SQL 中的 distinct 和 row_number() over() 的区别及用法
1 前言 在咱们编写 SQL 语句操作数据库中的数据的时候,有可能会遇到一些不太爽的问题,例如对于同一字段拥有相同名称的记录,我们只需要显示一条,但实际上数据库中可能含有多条拥有相同名称的记录,从而在 ...
- SQL中distinct 和 row_number() over() 的区别及用法
1 前言 在咱们编写 SQL 语句操作数据库中的数据的时候,有可能会遇到一些不太爽的问题,例如对于同一字段拥有相同名称的记录,我们只需要显示一条,但实际上数据库中可能含有多条拥有相同名称的记录,从而在 ...
- angularjs中provider,factory,service的区别和用法
angularjs中provider,factory,service的区别和用法 都能提供service,但是又有差别 service 第一次被注入时实例化,只实例化一次,整个应用的生命周期中是个单例 ...
- 转 Java中final、finally、finalize的区别与用法
Java中final.finally.finalize的区别与用法 1.简单区别:final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承.finally是异常处理语句结构 ...
- sql中内联 和外联 区别
sql中内联 和外联 区别 2007-05-15 17:37 这个概念一般看书不好理解.其实夜简单.有例子就简单了. 比如: 表A(主表) cardid username 16 aa 23 bb 25 ...
- SQL中IS NOT NULL与!=NULL的区别
平时经常会遇到这两种写法:IS NOT NULL与!=NULL.也经常会遇到数据库有符合条件!=NULL的数据,但是返回为空集合.实际上,是由于对二者使用区别理解不透彻. 默认情况下,推荐使用 IS ...
- jQuery 中 jQuery(function(){})与(function(){})(jQuery) 的区别及用法
query是优秀的Javascrīpt框架.我们现在来讨论下在 Jquery 中两个页面载入后执行的函数. $(document).ready(function(){ // 在这里写你的代码... } ...
- SQL中on条件与where条件的区别(转载)
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1. on条件是在生成临时表时使用的条 ...
- 【SQL】SQL中on条件与where条件的区别
#前言 数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1.on条件是在生成临时表时 ...
随机推荐
- android学习四---Activity和Intent
1.android项目资源深入了解 在深入学习android之前,先好好玩玩手机上的应用,大部分程序都有一个图标,点开图标,程序启动,一定时间后,程序会跳转到第一个界面,比如手机QQ,点开图标,会跳出 ...
- oradebug工具使用(转载)
在之前的HangAnalyze 中有使用oradebug命令,在这篇文章里,我们主要是重点看一下这个oradebug命令: Oracle HANGANALYZE 功能诊断 DB hanging htt ...
- ununtu16.04+python3+selenium+firefox环境搭建
一.初始配置: 1.安装完系统并配置好地址及DNS.2.设置root密码: sudo passwd root 3.更改云源: sudo cp /etc/apt/sources.list /etc/ap ...
- HDU - 3829 Cat VS Dog (二分图最大独立集)
题意:P个小朋友,每个人有喜欢的动物和讨厌的动物.留下喜欢的动物并且拿掉讨厌的动物,这个小朋友就会开心.问最多有几个小朋友能开心. 分析:对于每个动物来说,可能既有人喜欢又有人讨厌,那么这样的动物实际 ...
- Spark机器学习4·分类模型(spark-shell)
线性模型 逻辑回归--逻辑损失(logistic loss) 线性支持向量机(Support Vector Machine, SVM)--合页损失(hinge loss) 朴素贝叶斯(Naive Ba ...
- MySQL-5.7设置InnoDB表数据文件存储位置
1.表空间 Innodb存储引擎可将所有数据存放于ibdata*的共享表空间,也可将每张表存放于独立的.ibd文件的独立表空间. 共享表空间以及独立表空间都是针对数据的存储方式而言的. 共享表空间: ...
- zabbix3.0安装(本文引用51cto博主烂泥行天下的文章,我也是参考他写的文章安装的zabbix)
但是由于他文章写的时间有点久了,上面的关于安装zabbix之前需要安装的zabbix3.0yum源的链接失效了,所有我找了2个能用的zabbix 3.0yum源,其他的就不再写了 安装zabbix3. ...
- [Android]AndFix使用说明
AndFix使用说明 AndFix,全称是Android hot-fix.是阿里开源的一个热补丁框架,允许APP在不重新发布版本的情况下修复线上的bug.支持Android 2.3 到 6.0,并且支 ...
- Linux7关闭防火墙
RedHat Enterprise Linux 7关闭防火墙方法 在之前的版本中关闭防火墙等服务的命令是 service iptables stop /etc/init.d/iptables stop ...
- 分布式技术 webapi 路由追加html、aspx、shtml 适用于 对接 安卓、IOS
首先是这样,在对接安卓和IOS或者是第三方调用的接口,我需要在服务端返回一个带.html/.aspx这样后缀的接口. 例子如下图:http://localhost:64131/api/UsersInf ...