你真的会玩SQL吗?冷落的Top和Apply

简介:

你真的会玩SQL吗?系列目录

你真的会玩SQL吗?之逻辑查询处理阶段

你真的会玩SQL吗?和平大使 内连接、外连接

你真的会玩SQL吗?三范式、数据完整性

你真的会玩SQL吗?查询指定节点及其所有父节点的方法

你真的会玩SQL吗?让人晕头转向的三值逻辑

你真的会玩SQL吗?EXISTS和IN之间的区别

你真的会玩SQL吗?无处不在的子查询

你真的会玩SQL吗?Case也疯狂

你真的会玩SQL吗?表表达式,排名函数

你真的会玩SQL吗?简单的 数据修改

你真的会玩SQL吗?你所不知道的 数据聚合

你真的会玩SQL吗?透视转换的艺术

你真的会玩SQL吗?冷落的Top和Apply

你真的会玩SQL吗?实用函数方法汇总

你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(上)

你真的会玩SQL吗?玩爆你的数据报表之存储过程编写(下)

 

本章预先想写一些Top和Apply基本的用法,但好像没什么意义,所以删掉了一些无用的东西,只留下几个示例,以保证系列的完整性。

Top和Apply解决的常见问题,如返回每个雇员的3个最新订单,订单的时间越新优先级就越高,但还需要引入一个决胜属性,以确定时间桢的订单的优先级,如可用id作为决胜属性。这里提供的解决方案比其它方案要简单得多,且执行速度更快。

返回每个雇员的3个最新订单:

复制代码
SELECT  empid ,
        orderid ,
        custid ,
        orderdate ,
        requireddate
FROM    sales.orders AS o1
WHERE   orderid IN ( SELECT TOP 3
                            orderid
                     FROM   sales.orders AS o2
                     WHERE  o2.empid = o1.empid
                     ORDER BY orderdate DESC ,
                            orderid DESC )
复制代码

运用APPLY解决:

复制代码
SELECT  e.empid ,
        a.orderid ,
        a.custid ,
        a.orderdate ,
        a.requireddate
FROM    hr.employees AS e
        CROSS APPLY ( SELECT TOP 3
                                orderid ,
                                custid ,
                                orderdate ,
                                requireddate
                      FROM      sales.orders AS o
                      WHERE     o.empid = e.empid
                      ORDER BY  orderdate DESC ,
                                orderid DESC
                    ) AS a
复制代码

先扫描employees 获得empid,对每个empid值对orders表查询返回 该雇员的3个最新订单。这里可以返回多个属性。

还有一种解决方案在特定情况下竟然比使用APPLY运算符的方法还要快,使用ROW_NUMBER函数。先为每个订单计算行号,按empid进行分区,并按orderdate desc, orderid desc 顺序排序。然后在外部查询中,只筛选行号小于或等于3的行。

如下:

复制代码
SELECT  orderid ,
        custid ,
        orderdate ,
        requireddate
FROM    ( SELECT    orderid ,
                    custid ,
                    orderdate ,
                    requireddate ,
                    ROW_NUMBER() OVER ( PARTITION BY empid ORDER BY orderdate DESC , orderid DESC ) AS rownum
          FROM      sales.orders
        ) AS d
WHERE   rownum <= 3 
复制代码

 

 练习:

从学生表中选取对应班级的前num名学生成绩

复制代码
--显示结果
/*
bj         xh   name       cj
---------- ---- ---------- -----------
一班         A006 A6         100
一班         A005 A5         99
一班         A001 A1         89
一班         A002 A2         89
 
二班         B001 B7         100
二班         B001 B6         99
二班         B001 B9         97
二班         B001 B8         90
二班         B001 B5         88
*/
复制代码

 

复制代码
-- 创建测试表
declare @student table(        ---学生表
bj varchar(10),          -- 班级
xh char(4),                 -- 学号
name varchar(10),         -- 姓名   
cj int)                     -- 成绩
 
 
declare @tj table(            ---统计表
bj varchar(10),          -- 班级
num int)                 -- 人数  :从学生表中选取对应班级的前num名学生成绩 
 
set nocount on
 
-- 添加测试数据
insert @student select '一班' ,'A001','A1',89
insert @student select '一班' ,'A002','A2',89
insert @student select '一班' ,'A003','A3',59
insert @student select '一班' ,'A004','A4',80
insert @student select '一班' ,'A005','A5',99
insert @student select '一班' ,'A006','A6',100
insert @student select '一班' ,'A007','A7',82
 
insert @student select '二班' ,'B001','B1',19
insert @student select '二班' ,'B001','B2',81
insert @student select '二班' ,'B001','B3',69
insert @student select '二班' ,'B001','B4',86
insert @student select '二班' ,'B001','B5',88
insert @student select '二班' ,'B001','B6',99
insert @student select '二班' ,'B001','B7',100
insert @student select '二班' ,'B001','B8',90
insert @student select '二班' ,'B001','B9',97 
 
 
insert @tj select '一班',3
insert @tj select '二班',5
 
复制代码

 参考SQL:

复制代码
-- 2005.T-SQL 
select t.bj,s.xh,s.name,s.cj
from @tj t
cross apply (
    SELECT TOP(t.num) 
            with ties       -- 加 with ties,一班将选出4个人(2个人并列第三名) 
        xh,name,cj 
    from @student
    where t.bj=bj            -- 加where 功能类似于 inner join ;不加类似于 cross join
    order by cj desc 
)s
order by case when t.bj='一班' then 1 else 2 end asc,s.cj desc,s.xh asc    ---排序
 
复制代码

 本文转自欢醉博客园博客,原文链接http://www.cnblogs.com/zhangs1986/p/4915130.html如需转载请自行联系原作者


欢醉

相关文章
|
6月前
|
SQL Oracle 关系型数据库
|
3月前
|
SQL 数据挖掘 大数据
如何在 SQL Server 中使用 `SELECT TOP`
【8月更文挑战第10天】
145 7
如何在 SQL Server 中使用 `SELECT TOP`
|
4月前
|
SQL Oracle 关系型数据库
SQL SELECT TOP 子句
【7月更文挑战第12天】SQL SELECT TOP 子句。
45 14
|
4月前
|
SQL Oracle 关系型数据库
SQL SELECT TOP 子句
【7月更文挑战第13天】SQL SELECT TOP 子句。
29 5
|
5月前
|
SQL 关系型数据库 MySQL
SQL SELECT TOP, LIMIT, ROWNUM 子句
SQL SELECT TOP, LIMIT, ROWNUM 子句
39 2
SQL SELECT TOP, LIMIT, ROWNUM 子句
|
5月前
|
SQL Oracle 关系型数据库
SQL SELECT TOP 详解
SQL SELECT TOP 详解
|
5月前
|
SQL Oracle 关系型数据库
SQL SELECT TOP, LIMIT, ROWNUM 子句
SQL SELECT TOP, LIMIT, ROWNUM 子句
53 4
|
6月前
|
SQL Oracle 关系型数据库
SQL SELECT TOP, LIMIT, ROWNUM 子句
SQL SELECT TOP, LIMIT, ROWNUM 子句
41 3
|
6月前
|
SQL 关系型数据库 Java
实时计算 Flink版操作报错之在阿里云DataHub平台上执行SQL查询GitHub新增star仓库Top 3时不显示结果,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
SQL Oracle 关系型数据库
12SQL - TOP关键字
12SQL - TOP关键字
38 0
下一篇
无影云桌面