理解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,假如你没有使用则将返回随机的指定行数数据。

T-SQL基础--TOP的更多相关文章

  1. 黑马程序员+SQL基础(上)

    黑马程序员+SQL基础 ---------------<a href="http://edu.csdn.net"target="blank">ASP ...

  2. 数据库学习---SQL基础(一)

     数据库学习---SQL基础(一) 数据库学习---SQL基础(二) 数据库学习---SQL基础(三) SQL(struct query language)结构化查询语言:一种专门与数据库通信的语言, ...

  3. sql基础语法大全 转载过来的,出处忘了!

    一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备 ...

  4. sql基础知识集锦

    Sql常用语法 下列语句部分是Mssql语句,不可以在access中使用. SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT ...

  5. 信安周报-第02周:SQL基础

    信安之路 第02周 Code:https://github.com/lotapp/BaseCode/tree/master/safe 前言 本周需要自行研究学习的任务贴一下: 1.概念(推荐) 数据库 ...

  6. SQL基础语句(详解版)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/CZXY18ji/article/deta ...

  7. 常见SQL语句和SQL基础知识

    引自:http://blog.csdn.net/u012467492/article/details/46790205 SQL语句考察(一) 1.查询出每门课都大于80 分的学生姓名 name   k ...

  8. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  9. [SQL] SQL 基础知识梳理(二) - 查询基础

    SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...

  10. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

随机推荐

  1. windbg学习进阶之——windbg环境变量配置

    接触性能调优以来一直想学下windbg分析dump,每次看老师几个命令就能找到很底层的问题原因那简直就是羡慕加崇拜啊~但是这接近一年了,愣是没啥进展呢,主要就是在今天整理的这部分卡住了...这理由找的 ...

  2. 【转】php中XML、XSLT的结合运用

    原文:http://blog.csdn.net/bjbs_270/article/details/140253   下面我要讲的是一个简单的从数据库中抽取数据,生成XML文档,使用XSLT转换成HTM ...

  3. c++错误代码1

    今天敲c++,出现一个错误,这个题目错误代码如下: 并没有提示有错误而终止. 运行结果却错了: 很明显,错误的地方是变量r没有初始化. 这让我知道了,这种情况下的某些变量未经初始化而使用编译器是不会报 ...

  4. 算法:二分查找(python版)

    #!/usr/bin/env python #coding -*- utf:8 -*- #二分查找#时间复杂度O(logn)#一个时间常量O(1)将问题的规模缩小一半,则O(logn) import ...

  5. java 本地目录文件删除 ***最爱那水货

    /** * @note 删除目录下的所有文件 * @param path * @return */ public static boolean delAllFile(String path){ boo ...

  6. 高性能 Windows Socket 组件 HP-Socket v2.3.1-beta-1 发布

    HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP ...

  7. rabbitmq binary/other_system内存占用很高

    最近有台服务器的MQ应用占用内存比较偏高,如下: 但是看控制台本身内存中消息积压并不多, 查看rabbtmqctl发现,binary data和other data占据了绝大部分的内存,如下: {me ...

  8. Redis-持久化

    Redis 持久化 Redis 提供了不同持久化范围的选项: RDB 持久化以指定的时间间隔执行数据集的即时点(point-in-time)快照. AOF 持久化在服务端记录每次收到的写操作,在服务器 ...

  9. 使用快捷键提升C#开发效率

    好的工具能帮我们提升开发效率,能用工具去做的事情尽量使用工具,让我们的开发尽量自动化是提升开发效率的关键因素. 很多人都用过Resharper,也被Resharper超多的快捷键所折服,本篇文章我总结 ...

  10. ASP.Net之数据绑定

    ---恢复内容开始--- [概述]数据绑定是指从数据源获取数据或向数据源写入数据.简单的数据绑定可以是对变量或属性的绑定,比较复杂的是对ASP.NET数据绑定控件的操作 1.简单的属性绑定 基于属性的 ...