共计 1505 个字符,预计需要花费 4 分钟才能阅读完成。
导读 | 最近帮业务部门梳理业务报表,其中有个需求是就算某指标等待时间最长的前百分之十,其实就是对等待时长进行倒序排序后,取结果集的前百分之十。这个需求在 SQL Server 和 Oracle 上都很容易实现,甚至是在 MySQL 8.0 也很容易实现,只是恰好我们业务数据库是 MySQL 5.7。 |
先给大家介绍下不同数据库平台的实现方法。
SQL Server 实现方法
SQL Server 上有个 TOP Percent 的方法可以直接取结果的前(或后)百分之 N。
例如有如下一张 City 表:
我们取前 10% 的数据记录可以这样写:
SELECT | |
TOP 10 PERCENT | |
* | |
FROM City | |
ORDER BY ID DESC |
结果如下:
Oracle 实现方法
Oracle 有个 ROWNUM 伪列可以用来帮助我们计算前百分之 N。
ROWNUM 伪列的特点:
在使用 ROWNUM 进行查询时,请注意:
SELECT COUNT(*) CNT FROM City
然后根据 count 聚合查询总条数乘以百分比,来确定要查询的条数。
SELECT 0.1*COUNT(*) CNT FROM City
最后取出伪列小于共有数据的百分比的数据。
SELECT * FROM CITY | |
WHERE ID IN | |
( | |
SELECT ID FROM | |
(SELECT ID FROM CITY ORDER BY ID DESC) | |
WHERE ROWNUM | |
注意:Oracle 不支持子查询内 ORDER BY,需要在外面再嵌套一层。 | |
MySQL 8.0 的实现方法 | |
MySQL 8.0 的实现方法主要是借助窗口函数 ROW_NUMBER() OVER()。其实就是给排好序的集合添加一个自增长列,与 Oracle 的 ROWNUM 有点类似。 | |
SELECT * FROM | |
( | |
SELECT *, | |
ROW_NUMBER() OVER(ORDER BY ID DESC) rn | |
FROM City | |
ORDER BY ID DESC | |
) a | |
WHERE a.rn | |
MySQL 5.X 的实现方法 | |
我们知道 MySQL 5.X 是没有开窗函数 ROW_NUMBER() OVER() 的,那该如何实现呢? | |
这里我们需要借助变量来实现,其实思路还是创建一个自增长列,只是方法不同。 | |
SELECT | |
A.*, | |
@row_num:=@row_num+1 AS ROW_NUM | |
FROM | |
City A , (SELECT @row_num:=0) B | |
ORDER BY ID DESC | |
这样我们就可以得到一张有自增长列的结果集了,接下来还是按照上面类似的方法,取前 10% 即可。 | |
SELECT * FROM | |
( | |
SELECT | |
A.*, | |
@row_num:=@row_num+1 AS ROW_NUM | |
FROM | |
City A , (SELECT @row_num:=0) B | |
ORDER BY ID DESC | |
) C | |
WHERE C.ROW_NUM | |
其实 MySQL 5.X 也挺简单的,只是当时不怎么想用变量,想看看有没有其他办法,最后发现还是得用变量。 | |
以上就是不同平台的数据库求前百分之 N 的方法了,代码可以验证一下收藏起来留着下次直接套用。 | |
总结 | |
其中有涉及一些知识点,需要小伙伴们自己去进一步了解: | |
SQL Server 的 TOP PERCENT。 | |
Oracle 的 ROWNUM,子查询排序。 | |
ROW_NUMBER() OVER()。 | |
MySQL 的变量。 | |
阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配 | |
腾讯云新客低至 82 元 / 年,老客户 99 元 / 年 | |
代金券:在阿里云专用满减优惠券 | |
正文完
星哥玩云-微信公众号
