鲜荣彬
Herry

  对于top关键字,你也许很熟悉他的用法,但你知道top查询返回的是一个表结果还是游标呢?

  当使用top的,同一个order by字句既担当了为top决定行的逻辑优先顺序的角色,同时也担当了它的常规角色(展示数据),只是最终生成的结果由表变成了具有固定顺序的游标。

   用法有下面三种:1、关键字 percent,SQL Server会按照百分比计算应该返回的的满足条件的行数(向上取整);

  用法  select top 1 percent orderid from ordervalues。

           2、选择需要的前几行,常用于分页;

  用法 select top 10 orderid from ordervalues。

        3、返回与top n行中最后一行的排序值相同的其他所有行,须添加 with ties选项,如果排序值有多个,则以最后一个排序值为准,这里为custid。

  用法 select top(5) with ties orderid,orderdate,custid,empid
       from orders
              order by empid desc,custid

  over子句,用于为行定义一个窗口,以便进行特定的运算。我们可以把行的窗口简单的认为是运算将要操作的一个行的集合。由于over子句可以为聚合函数和排名函数提供一个行的窗口,这些函数也称为开窗函数。带有空的圆括号的over子句会提供所有行进行计算,这里的所有行并不一定是在from 子句中出现的那些表中的所有行,而是在from、where、group by,以及having处理阶段才完成后仍然可以用的那些行。那么,什么地方才可以用over子句呢?? answer就是只有在select和order by处理阶段。

  以下例句中的OrderValues是一个视图(其中数据可以在我的上一篇博文可以下载)。创建此视图的语句为

CREATE VIEW OrderValues
AS

SELECT O.orderid, O.custid, O.empid, O.shipperid, O.orderdate,
  CAST(SUM(OD.qty * OD.unitprice * (1 - discount))
       AS NUMERIC(12, 2)) AS val
FROM Orders AS O
  JOIN OrderDetails AS OD
    ON O.orderid = OD.orderid
GROUP BY O.orderid, O.custid, O.empid, O.shipperid, O.orderdate;

 

  请看下面Sql语句。其中sum(val) over() as totalValue表示返回当前所有行的val字段的和,如果我们想得到当前行具有相同custid值得val之和,那么则可以用partition  by 字句指定求和的关键字。

1 select * from OrderValues;
2 select orderid,custid,val,
3     sum(val) over() as totalvalue,
4     sum(val) over(partition by custid) as custtotalvalue
5 from OrderValues;

   当然,over子句的一个优点是能够在返回基本行的同时,可以将聚合函数和基本列共同使用。比如下面Sql语句。

1 select orderid,custid,val,
2     100.*val/sum(val) over() as pctall,
3     100.*val/sum(val) over(partition by custid) as pctust
4 from ordervalues;

  不仅如此,over子句也支持四种排名函数,row_number(),rank(),dense_rank(),ntile,如下面Sql语句。

1 select orderid,custid,val,
2        row_number() over(order by val) as rownum,
3        rank() over(order by val) as rank,
4        dense_rank() over(order by val) as dense_rank,
5        ntile(10) over(order by val) as ntile
6 from ordervalues
7 order by val

  其中,row_number函数用于为子查询的结果集中的各行分配递增的序列号,其逻辑顺序通过over子句中的order by语句制定,因此,order by子句的字段的值最好在数据库中是唯一的。NTILE函数可以把结果中的行关联到组,NTILE(n)中的n表示制定组的数目,并为每一行分配一个所属组的编号,因此组的大小是830/10=83,即第一个组里面有83行数据。当然,排名函数也支持partition by语句。rank()与dense_rank()可以为具有相同逻辑排序值得所有行产生相同的排名。这两个函数的区别是,rank()表示之前有多少行具有更低的排序值,而密集排名函数则表示之前有多少个更低的排序值,注意一个是行,一个值。

posted on 2012-11-21 22:07  Herry彬  阅读(502)  评论(0编辑  收藏  举报