T-SQL基础--TOP
理解TOP子句
众所周知,TOP子句可以通过控制返回行的数量来影响查询。
我们知道TOP子句能很容易的满足返回指定行数的子集,接下来有一些例子来展示什么情况下使用TOP子句来返回一个结果集;
- 你打算返回的恰好是一个记录的子集来验证你代码;
- 你仅仅需要确定至少一行数据满足特定的Where条件;
- 你的业务需求指示你仅仅返回前面的几行数据,基于一个特定的Where条件;
为了去解释TOP子句的如何工作,我将列举几个实例,使你能够更容易理解并观察使用TOP子句的影响返回值得细微差别。
TOP 的语法
语法很简单,可以将TOP加在任何如 SELECT、DELETE, INSERT, or UPDATE 的语句中:
TOP (expression) [PERCENT]
[WITH TIES]
“expression”的值是一个数字,,如果PERCENT的可选项被启用则数字将被转换成一个float 类型,否则姜维BIGINT类型。可以指定数字也可以使用局部变量。
可选项WITH TIES ,用来包含具有系统值得数据,需要注意的是该选项支队带有Order by的子句有效。
举例说明:
现有数据:
简单实例1
-- 找到两个SalesAgent 根据SalesAmount倒序。先排序在选出前两个,如果没有Order by 则此数据会随即返回(没有主键)
SELECT TOP(2) SalesAgent, Region, SalesAmount
FROM dbo.HectorSales
ORDER BY SalesAmount DESC;
运行结果:
SalesAgent Region SalesAmount
------------------------------ ---------- --------------------------
Nick Potts East 9834212.87
Mary Johnson West 8723412.61
使用百分比的查询
If you want to return a percentage of the top records in a set then you need to use the TOP clause with the PERCENT option. To demonstrate using the PERCENT option look at Listing 3.
-- 查询前百分之50的数据,按照SalesAmount
SELECT TOP(50) PERCENT SalesAgent, Region, SalesAmount
FROM dbo.HectorSales
ORDER BY SalesAmount DESC;
查询结果:
SalesAgent Region SalesAmount
----------------------------- ---------- ---------------------------
Nick Potts East 9834212.87
Mary Johnson West 8723412.61
Sam Holder East 8723412.61
Stan Morris East 4562341.67
Lori Morin East 2000111.67
使用变量的TOP查询
--不带百分比的查询
DECLARE @Number INT = 2;
SELECT TOP(@Number) SalesAgent, Region, SalesAmount
FROM dbo.HectorSales
ORDER BY SalesAmount DESC;
-- 带百分比的
SET @Number = 50;
SELECT TOP(@Number) PERCENT SalesAgent, Region, SalesAmount
FROM dbo.HectorSales
ORDER BY SalesAmount DESC;
使用 WITH TIES 可选项
按照值进行排序,如果有相同的则一并显示出来
-- 找出SalesAmount 最大的前两个。实际是3个
SELECT TOP(2) WITH TIES SalesAgent, Region, SalesAmount
FROM dbo.HectorSales
ORDER BY SalesAmount DESC;
查询结果:
SalesAgent Region SalesAmount
------------------------------ ---------- --------------------------
Nick Potts East 9834212.87
Mary Johnson West 8723412.61
Sam Holder East 8723412.61
正如我们看到的,返回了3行而不是2行,因为第三行和第二行的值是相同的。
使用TOP子句实现更新
如何使用TOP子句限制更新的行数,如下:
UPDATE TOP (2) dbo.HectorSales
SET SalesAmount = 100000.00
FROM dbo.HectorSales
WHERE Region = 'West'
更新后查询Region = 'West'的结果
SalesAgent Region SalesAmount
------------------------------ ---------- --------------------------
John Smith West 100000.00
Mary Johnson West 100000.00
Doris Bean West 2000111.67
Martin Derrick West 120834.81
Don Olson West 508921.48
当然也可以使用其他不同的方式来更新,先查询出前2的数据,然后将符合前2的数据进行更新,如下:
UPDATE dbo.HectorSales
SET SalesAmount = 6666666.00
FROM
(SELECT TOP(2) SalesAgent FROM dbo.HectorSales
WHERE Region = 'West'
ORDER BY SalesAmount DESC) TS
WHERE dbo.HectorSales.SalesAgent = TS.SalesAgent
更新后的结果:
SalesAgent Region SalesAmount
------------------------------ ---------- --------------------------
John Smith West 100000.00
Mary Johnson West 100000.00
Doris Bean West 6666666.00
Martin Derrick West 120834.81
Don Olson West 6666666.00
使用TOP完成Insert 语句
例如我打算将SalesAmount 最多的两个SalesAgent 插入到表dbo.TopTwoSales 的agent 里面。
INSERT TOP(2) INTO dbo.TopTwoHectorSales
SELECT * FROM dbo.HectorSales
ORDER BY SalesAmount DESC;
SELECT * FROM dbo.TopTwoHectorSales;
结果集如下:
SalesAgent Region SalesAmount
------------------------------ ---------- --------------------------
John Smith West 100000.00
Mary Johnson West 100000.00
通过查询结果我们发现插入的两行,并不是SalesAmount 最大的两行,因为我将TOP放在了Insert 后面,SQLServer 认为从子结果集中的前两行,这样的话实际上子结果集是随即的。为了纠正之前的问题,我这样写:
INSERT INTO dbo.TopTwoHectorSales
SELECT TOP(2) * FROM dbo.HectorSales
ORDER BY SalesAmount DESC;
SELECT * FROM dbo.TopTwoHectorSales;
改正后的结果:
SalesAgent Region SalesAmount
------------------------------ ---------- --------------------------
Nick Potts East 9834212.87
Sam Holder East 8723412.61
使用TOP完成DELETE语句
BEGIN TRANSACTION;
DELETE FROM dbo.HectorSales
WHERE SalesAgent in (SELECT TOP(2) SalesAgent FROM dbo.HectorSales
ORDER by SalesAmount ASC);
SELECT * FROM dbo.HectorSales;
ROLLBACK;
结果如下:
SalesAgent Region SalesAmount
------------------------------ ---------- --------------------------
John Smith West 100000.00
Doris Bean West 6666666.00
Martin Derrick West 120834.81
Don Olson West 6666666.00
Sam Holder East 8723412.61
Nick Potts East 9834212.87
Lori Morin East 2000111.67
Stan Morris East 4562341.67
Report 12: Rows inserted into dbo.TopTwoHectorSales table using ORDER BY
当然如果想包含相同的值,使用WITH TIES
DELETE FROM dbo.HectorSales
WHERE SalesAgent in (SELECT TOP(2) WITH TIES SalesAgent FROM dbo.HectorSales
ORDER by SalesAmount ASC);
SELECT * FROM dbo.HectorSales;
与上一个相比,这个代码将会多删除掉一个SalesAmount 1000000.00数据
谨慎使用TOP关键在UNION、EXCEPT和INTERSECT语句中
创建一个表,插入初始数据。
CREATE TABLE dbo.Sales (
AgentName varchar(30),
Region varchar(10),
SalesAmount decimal(10,2));
INSERT INTO dbo.Sales VALUES
('John Smith', 'West',1012302.01),
('Mary Johnson', 'West',2453202.89),
('Doris Bean', 'West',99001.43),
('Sam Holder', 'East',8723412.61),
('Nick Potts', 'East',9834212.87),
('Jason Thomas', 'East',13424.51);
将东西部最高的SalesAmount 筛选出来并联
SELECT AgentName, Region, SalesAmount FROM
(
SELECT TOP(1) AgentName, Region, SalesAmount
FROM dbo.Sales
WHERE Region = 'East'
ORDER BY SalesAmount DESC ) East
UNION
SELECT AgentName, Region, SalesAmount FROM
(
SELECT TOP(1) AgentName, Region, SalesAmount
FROM dbo.Sales
WHERE Region = 'West'
ORDER BY SalesAmount DESC ) West
ORDER BY SalesAmount DESC;
总结
TOP关键字,让我们可以返回指定行数的数据,也能指定行数或者百分比的数据。为了确保结果集的一致性,一定要保证使用ORDER BY,假如你没有使用则将返回随机的指定行数数据。
- HDUOJ-----2852 KiKi's K-Number(树状数组+二分)
- nyoj----522 Interval (简单树状数组)
- HDUOJ-----2838Cow Sorting(组合树状数组)
- HDUOJ---2642Stars(二维树状数组)
- HDUOJ -----Color the ball
- poj-----Ultra-QuickSort(离散化+树状数组)
- HDUOJ---1241Oil Deposits(dfs)
- HDUOJ------2398Savings Account
- HDUOJ-----2399GPA
- HDUOJ----旋转的二进制
- HDUOJ---3743Frosh Week(BIT+离散化)
- Node.js新手必须知道的4个JavaScript概念
- HUDOJ-----1394Minimum Inversion Number
- 提升 Node.js 应用性能的 5 个技巧
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 视图在SQL中的作用是什么,它是怎样工作的?
- Linux命令行上如何使用日历详解
- 在Linux下修改和重置root密码的方法(超简单)
- 在Centos上搭建Maven中央仓库的方法
- 详解Ubuntu16.04启动器图标异常解决方法
- Linux(ubuntu)下实现增加/删除文件权限
- Vim中文件编码处理与重新打开乱码文件详解
- Linux常用命令mkdir详解
- CentOS6.5环境下使用rsync增量同步备份文件的方法
- Linux 搭建Git服务器的方法
- Linux中无法远程连接数据库问题的解决方法
- VIM实现文件快速跳转插件详解
- 详解linux usb host驱动编写入门
- CentOS服务器平台搭建mysql主从复制与读写分离的方法
- Centos7中添加、删除Swap交换分区的方法