第七十六章 SQL命令 TOP

第七十六章 SQL命令 TOP

指定返回多少行的SELECT子句。

大纲

SELECT  [DISTINCT clause] 
  [TOP {[((]int[))] | ALL}]
  select-item{,select-item}

参数

  • int - 限制返回到指定整数的行数。
    int参数可以是一个正整数、一个动态SQL输入参数(?)或一个解析为正整数的嵌入式SQL主机变量(:var)。在动态SQL中,int值可以选择用单括号或双括号括起来(双括号是首选语法);
    这些括号禁止在相应的缓存查询中对int值进行文字替换。
  • ALL - TOP ALL仅在子查询或CREATE VIEW语句中有意义。
    它用于在这些情况下支持使用ORDER BY子句,满足在子查询或CREATE VIEW中使用的查询中ORDER BY子句必须与TOP子句配对的要求。
    TOP ALL不限制返回的行数。

描述

可选的TOP子句出现在SELECT关键字和可选的DISTINCT子句之后,以及第一个选择项之前。

TOP关键字用于动态SQL和基于指针的嵌入式SQL。
在非游标嵌入式SQL中,TOP关键字的唯一有意义的用法是TOP 0
任何其他TOP int(其中int是任何非零整数)都是有效的,但没有意义,因为非游标嵌入式SQL中的SELECT总是最多返回一行数据。

SELECT语句的TOP子句将返回的行数限制为int中指定的行数。
如果没有指定TOP子句,则默认显示满足SELECT条件的所有行。
如果指定了TOP子句,则显示的行数或行数要么为int,要么为满足查询谓词要求的所有行(以较小的为准)。
如果指定ALL, SELECT将返回表中满足查询谓词要求的所有行。

如果查询中没有指定ORDER BY子句,那么将哪些记录作为“top”行返回是不可预测的。
如果指定了ORDER BY子句,则顶部的行与该子句中指定的顺序一致。

DISTINCT子句(如果指定)应用于TOP之前,指定返回(最多)int个唯一值。

当所有行已交付时,TOP短路。
因此,如果选择直到获得SQLCODE 100,则设置SQLCODE 100FETCH是即时的。

当通过视图或FROM子句子查询访问数据时,可以使用%vid视图ID而不是(或附加)TOP子句来限制返回的行数。

TOP int值

int数值可以是整数、数字字符串、动态SQL输入参数(?)或解析为整数值的输入主机变量(:var)。

int值指定要返回的行数。
允许的值是0和正数。
不能将int值指定为算术表达式、字段名、子查询列别名、标量函数或聚合函数。
小数或数字字符串被解析为其整数值。
0(0)是一个有效的整型值。
TOP 0执行查询,但不返回数据。

TOP ALL必须在查询中指定为关键字。
不能将ALL指定为?
输入参数或:var主机变量值。
查询解析器将以这种方式提供的字符串“ALL”解释为值为0的数字字符串。

注意,TOP参数元数据返回为xDBC数据类型12 (VARCHAR),而不是4 (INTEGER),因为可以将TOP int指定为数字字符串或整数。

TOP和缓存查询

int值可以用括号指定,也可以不使用括号指定。
这些括号影响如何缓存动态SQL查询(非游标嵌入式SQL查询不缓存)。
没有括号的整型值被转换为 a?
缓存查询中的参数变量。
这意味着重复使用不同的TOP int值调用相同的查询将调用相同的缓存查询,而不是每次都准备和优化查询。

括起来的圆括号禁止文字替换。
例如,TOP(7))
int被括在括号中时,缓存的查询保留特定的int值。
使用相同的TOP int值重新调用查询将使用缓存的查询;
使用不同的TOP int值调用查询将导致SQL准备、优化和缓存这个新版本的查询。

TOP ALL不是缓存为 a?
参数变量。
ALL被解析为关键字,而不是字面量。
因此,使用TOP 7TOP ALL的相同查询将生成两个不同的缓存查询。

TOP和ORDER BY

TOP通常用于带ORDER BY子句的SELECT中。
注意,默认升序ORDER BY排序顺序认为NULL是最低值(" top "),后面跟着空字符串(")。

当指定ORDER BY子句时,在子查询SELECTCREATE VIEW SELECT中需要TOP
在这些情况下,可以指定TOP int(以限制返回的行数)或TOP ALL

TOP ALL只在子查询或CREATE VIEW语句中使用。
它用于在这些情况下支持使用ORDER BY子句,以满足在子查询或CREATE VIEW查询中ORDER BY子句必须与TOP子句配对的要求。
TOP ALL不限制返回的行数。
前所有…
ORDER BY不会改变默认的SELECT优化。
ALL关键字不能用括号括起来。

TOP 优化

默认情况下,SELECT优化以最快的时间返回所有数据。
同时添加TOP int子句和ORDER BY子句可以优化以最快的时间返回第一行。
(注意,这两个子句都需要更改优化。)
可以使用%SYS.PTools
StatsSQLTotalTimeToFirstRow属性返回返回第一行所需的时间。

以下是特殊情况下的优化:

  • 可能希望使用TOPORDER BY优化策略,而不限制返回的行数;
    例如,如您正在返回以页面单元显示的数据。
    在这种情况下,能希望发出一个TOP子句,该子句的int值大于行总数。
  • 可能希望限制返回的行数并指定它们的顺序,而不改变默认的SELECT优化。
    在这种情况下,指定TOP子句、ORDER BY子句和%NOTOPOPT关键字,以保留返回所有数据优化所需的最快时间。

TOP与聚合和函数

聚合函数或标量函数只能返回单个值。
如果查询选择项列表中只包含聚合和函数,则TOP子句的应用如下:

  • 如果选择项列表包含聚合函数,例如COUNT(*)AVG(Age),且不包含任何字段引用,则返回的行数不超过一行,无论TOP int值或ORDER BY子句是否存在。
    这些子句被验证,但被忽略。
    以下例子显示了这一点:
SELECT TOP 5 AVG(Age),CURRENT_TIMESTAMP(3) FROM Sample.Person
  /* returns 1 row */
SELECT TOP 1 AVG(Age),CURRENT_TIMESTAMP(3) FROM Sample.Person ORDER BY Age
  /* returns 1 row */
  • 如果选择项列表包含一个或多个标量函数、表达式、文字(如%TABLENAME)、子查询或宿主变量,并且不包含任何字段引用或聚合,则应用TOP子句。
    下面的例子显示了这一点:
SELECT TOP 5 ROUND(678.987,2),CURRENT_TIMESTAMP(3) FROM Sample.Person
  /* returns 5 identical rows */

返回的实际行数取决于表中的行数,即使在没有引用表字段时也是如此。
例如:

SELECT TOP 300 CURRENT_TIMESTAMP(3) FROM Sample.Person
  /* returns either the number of rows in Sample.Person
     or 300 rows, whichever is smaller */

当查询受到谓词条件的限制时,即使在选择项列表中没有引用表字段,返回的行数也会受到该条件的限制。
例如:

SELECT TOP 300 CURRENT_TIMESTAMP(3) FROM Sample.Person WHERE Home_State = 'MA'
  /* returns either the number of rows in Sample.Person
     where Home_State = 'MA'
     or 300 rows, whichever is smaller */
  • 如果SELECT语句不包含FROM子句,则不管TOP值如何,最多返回一行。
    例如:
SELECT TOP 5 ROUND(678.987,2),CURRENT_TIMESTAMP(3)
  /* returns 1 row */
  • DISTINCT子句进一步限制了TOP子句。
    如果不同的值比TOP值少,则只返回具有不同值的行。
    当仅引用标量函数时,只返回一行。
    例如:
SELECT DISTINCT TOP 15 CURRENT_TIMESTAMP(3) FROM Sample.Person
  /* returns 1 row */
  • TOP 0总是不返回任何行,不管选择项列表的内容是什么,也不管SELECT语句是包含FROM子句还是DISTINCT子句。

在非游标嵌入式SQL中,TOP 0查询不返回任何行,并设置SQLCODE=100;带有TOP 1(或任何其他TOP int值)的非游标嵌入式SQL查询返回一行并设置SQLCODE=0
在基于指针的嵌入式SQL中,获取循环的完成总是设置SQLCODE=100,而不管TOP int值如何。

示例

下面的查询返回从Sample检索到的前20行。
人按他们在数据库中的存储顺序排列。
这个记录顺序通常是不可预测的。

SELECT TOP 20 Home_State,Name FROM Sample.Person

下面的查询返回从Sample检索到的前20个不同的Home_State值。
人在升序排列顺序。

SELECT DISTINCT TOP 20 Home_State FROM Sample.Person ORDER BY Home_State

下面的查询返回前40个不同的FavoriteColor值。
“top”行反映了Sample中所有行的ORDER BY子句排序。
按降序(DESC)排序的人。
使用降序排序序列而不是默认的升序排序序列,因为众所周知FavoriteColors字段有null,它将出现在升序排序序列的顶部。

SELECT DISTINCT TOP 40 FavoriteColors FROM Sample.Person 
      ORDER BY FavoriteColors DESC

还要注意,在前面的示例中,由于FavoriteColors是一个列表字段,排序序列包括元素长度字节。
因此,六个字母的元素(YELLOW, PURPLE, ORANGE)被放在一起整理,在五个字母的元素(WHITE, GREEN等)之前列出。

动态SQL可以指定int值作为输入参数(用“?”表示)。
在下面的例子中,TOP ?
输入参数被%Execute方法设置为10:

ClassMethod Top()
{
    s myquery = "SELECT TOP ? Name,Age FROM Sample.Person"
    s tStatement = ##class(%SQL.Statement).%New()
    s qStatus = tStatement.%Prepare(myquery)
    s rset = tStatement.%Execute(10)
    d rset.%Display()
}

DHC-APP>d ##class(PHA.TEST.SQLCommand).Top()
Name    Age
yaoxin  31
xiaoli
姚鑫    7
姚鑫    7
...
10 Rows(s) Affected

以下基于游标的嵌入式SQL示例执行相同的操作:

ClassMethod Top1()
{
    SET topnum = 10
    &sql(
        DECLARE pCursorT CURSOR FOR
        SELECT TOP :topnum Name,Age INTO :name,:years FROM Sample.Person
    )
    &sql(OPEN pCursorT)
    q:(SQLCODE'=0)
    for { 
        &sql(FETCH pCursorT)
        q:SQLCODE
        w "Name=",name," Age=",years,!
    }
    &sql(CLOSE pCursorT)
}

DHC-APP>d ##class(PHA.TEST.SQLCommand).Top1()
Name=yaoxin Age=31
Name=xiaoli Age=
Name=姚鑫 Age=7
Name=姚鑫 Age=7
Name=姚鑫 Age=43
Name=姚鑫 Age=
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容