问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

SQL中怎么用聚合函数排序

发布网友 发布时间:2022-04-10 01:47

我来回答

4个回答

懂视网 时间:2022-04-10 06:08

排序函数是做什么的?

    排序函数的作用是基于一个结果集返回一个排序值。排序值就是一个数字,这个数字是典型的以1开始且自增长为1的行值。由ranking函数决定排序值可以使唯一的对于当前结果集,或者某些行数据有相同的排序值。在接下来我将研究不同的排序函数以及如何使用这些函数。

使用RANK函数的例子

    RANK函数每个分区的排序都是从1开始。“partition”是一组有相同指定分区列值的数据行的集合。如果一个分区中有相同排序列的值(这个列指定在ORDER BY后面),然后相同排序列值的行将会分配给相同的排序值。有点绕口,为了更好的理解,如何使用,让我们看下下面的语法:

RANK ( ) OVER ( [ PARTITION BY <partition_column> ] ORDER BY <order_by_column> )

这里有几个参数:

  • <partition_column>: 指定一个或者多个列名作为分区数据

  • <order by column>: 确定一个或者多个列然后用来对每个分区的输出数据进行排序

  • 注意:

    PARTITION BY子句是一个可选项。如是不使用,数据将按照一个分区对所有数据进行排序。如果指定了PARTITION BY子句,则每个分区的数据集都各自进行从1开始的排序。

    现在对RANK函数的语法和如何工作有了一定的理解,下面运行一对该函数的例子。需要说明一下我的例子的运行环境都是AdventureWorks2012 数据库,可以从网络上下载这里给出一个下载地址http://msftdbprodsamples.codeplex.com/releases/view/93587。

    下面是第一个使用RANK函数的例子:

    1234567USE AdventureWorks2012;GOSELECT PostalCode, StateProvinceID,       RANK() OVER         (ORDER BY PostalCode ASC) AS RankingValueFROM Person.AddressWHERE StateProvinceID IN (23,46);

     

    Code1: 只有RANK函数不分区

     

    运行代码后,结果集如下:

    PostalCode      StateProvinceID RankingValue
    --------------- --------------- --------------------
    03064           46              1
    03064           46              1
    03106           46              3
    03276           46              4
    03865           46              5
    83301           23              6
    83402           23              7
    83501           23              8
    83702           23              9
    83864           23              10
     

    如上所示,按照RANK函数使结果集按照列RankingValue进行了排序。在例子中排序是基于列PostalCode。每一个唯一的PostalCode 得到一个不同的排序值。这里PostalCode 为03054 有两行数据,它们的排序值都是1,因为有两个1,所以排序2就被跳过。其余的排序继续往下依次进行。

        由于RANK函数的分区子句没有使用,那么整个结果集被当做一个单一的分区。如果我打算按照独立的StateProvinceID 进行分区,然后进行排序我可以做按照如下的例子来执行:

    12345678USE AdventureWorks2012;GOSELECT PostalCode, StateProvinceID,       RANK() OVER         (PARTITION BY StateProvinceID          ORDER BY PostalCode ASC) AS RankingValueFROM Person.AddressWHERE StateProvinceID IN (23,46);

     

    Code 2: 使用分区子句

    运行代码后的结果集:

    PostalCode      StateProvinceID RankingValue
    --------------- --------------- --------------------
    83301           23              1
    83402           23              2
    83501           23              3
    83702           23              4
    83864           23              5
    03064           46              1
    03064           46              1
    03106           46              3
    03276           46              4
    03865           46              5

     

     

        在输出结果中分为了两个分区,一个分区是StateProvinceID 是23的,而另一个是包含StateProvinceID 值为46的、注意每个分区都是从1开始进行排序的。

    使用DENSE_RANK函数

     

        当运行RANK函数时,由于有一个相同的PostalCode ,输出结果会跳过一个排序值2,通过使用DENSE_RANK函数我能生成一个不省略改相同排序值的一个排序。该函数语法如下:

    DENSE_RANK ( ) OVER ( [ PARTIION BY <partition_column> ] ORDER BY <order_by_column> )

     

    语法中唯一的不同就是函数名称的改变。让我们运行下面的代码来研究下函数:

    12345678USE AdventureWorks2012;GOSELECT PostalCode, StateProvinceID,       DENSE_RANK() OVER         (PARTITION BY StateProvinceID          ORDER BY PostalCode ASC) AS RankingValueFROM Person.AddressWHERE StateProvinceID IN (23,46);

     

    Code3: 使用 DENSE_RANK

    结果集如下:

    PostalCode      StateProvinceID RankingValue
    --------------- --------------- --------------------
    83301           23              1
    83402           23              2
    83501           23              3
    83702           23              4
    83864           23              5
    03064           46              1
    03064           46              1
    03106           46              2
    03276           46              3
    03865           46              4

     

     

        根据结果集,可以看到PostalCode 03064 有相同的排序值,但是下一个PostalCode 的排序值为2而不是3了。与RANK函数的不同就是当有重复排序值时它能保证了排序序列中没有省略排序。

    使用NTILE 函数

    该函数将数据集合划分为不同的组。得到组的数量是根据指定的一个整数来确定的。下面就是NTILE 函数的语法:

    NTILE (integer_expression) OVER ( [ PARTIION BY <partition_column> ] ORDER BY <order_by_column> )

    Where:

  • <integer_expression>: 确定创建不同组的数量

  • <partition_column>:确定一个或者多个列用来进行分区数据

  • <order by column>: 确定一个或者多个列然后用来对每个分区的输出数据进行排序

  •  

    为了更好地理解,让我们回顾几个不同的例子。运行下面代码:

    1234567USE AdventureWorks2012;GOSELECT PostalCode, StateProvinceID,       NTILE(2) OVER         (ORDER BY PostalCode ASC) AS NTileValueFROM Person.AddressWHERE StateProvinceID IN (23,46);

     

    Code4: 使用NTILE 函数查询

    运行结果如下:

    PostalCode      StateProvinceID NTileValue
    --------------- --------------- --------------------
    03064           46              1
    03064           46              1
    03106           46              1
    03276           46              1
    03865           46              1
    83301           23              2
    83402           23              2
    83501           23              2
    83702           23              2
    83864           23              2

     

     

         通过观察结果集,能很容易发现有两个不同的NTileValue 的列值,1和2。两个不同的NTileValue 值被创建是因为这里我查询语句中指定了“NTILE(2)” 。这个括号内的值就是整数表达式,作用就是指定创建的组的数量。当看到结果集中有10行数据,前五行NTileValue 为1,后五行为2。不出所料整个结果集被平均分成了两组。

         如果不能被平均分配到不同个组的时候,比如参数导致有不能被整除的时候。当发生这种情况是那么将不能被整除的行按序放到每一个组内,知道所有的剩余行都被分配完毕。如下所示:

    12345678USE AdventureWorks2012;GODECLARE @Integer_Expression int = 4;SELECT PostalCode, StateProvinceID,       NTILE(@Integer_Expression) OVER         (ORDER BY PostalCode ASC) AS NTileValueFROM Person.AddressWHERE StateProvinceID IN (46,23);

     

    Code 5: NTile 查询不能平均分配结果集

    运行代码如下:

    PostalCode      StateProvinceID NTileValue
    --------------- --------------- --------------------
    03064           46              1
    03064           46              1
    03106           46              1
    03276           46              2
    03865           46              2
    83301           23              2
    83402           23              3
    83501           23              3
    83702           23              4
    83864           23              4

     

       这里直奔主题,10个结果行,参数为4需要分成4组,那么10除以4 余数为2。这意味着前两组会多一行比后两组。如上所示,在这个输出结果中1和2组都有3行,然后NTileValue 为3和4的组只有两行。

       跟RANK函数一样,我们也能使用partition 分区子句来创建分区下的NTILE 函数。当引入PARTITION BY 子句时,每个分区内部都从1开始进行NTILE排序。下面展示一下运行代码:

    123456789USE AdventureWorks2012;GODECLARE @Integer_Expression int = 3;SELECT PostalCode, StateProvinceID,       NTILE(@Integer_Expression) OVER         (PARTITION BY StateProvinceID          ORDER BY PostalCode ASC) AS NTileValueFROM Person.AddressWHERE StateProvinceID IN (46,23);

     

    Code 6: 使用分区子句后,使用NTile 查询不平均分组

    运行代码如下:

    PostalCode      StateProvinceID NTileValue
    --------------- --------------- --------------------
    83301           23              1
    83402           23              1
    83501           23              2
    83702           23              2
    83864           23              3
    03064           46              1
    03064           46              1
    03106           46              2
    03276           46              2
    03865           46              3

     

     

       通过结果集可以看到加入分区子句后对NTILE函数的影响。如果观察输出的NTileValue列值,可以发现排序从StateProvinceID  为46开始重新从1开始。这就是加入“PARTITION BY StateProvinceID”子句的作用,先分区在分组排序。

    使用 ROW_NUMBER 函数

        当打算为输出的行生成一个行号时,行号顺序地自增长,步长为1.为了完成目标我们需要使用ROW_NUMBER 函数。

    下面是使用ROW_NUMBER 的例子:

    ROW_NUMBER () OVER ( [ PARTIION BY <partition_expressions> ] ORDER BY <order_by_column> )

     

    代码如下:

    1234567USE AdventureWorks2012;GOSELECT PostalCode, StateProvinceID,       ROW_NUMBER() OVER         (ORDER BY PostalCode ASC) AS RowNumberFROM Person.AddressWHERE StateProvinceID IN (46,23);

     

    Code  7: 使用ROW_NUMBER 函数

    运行结果如下:

    PostalCode      StateProvinceID RowNumber
    --------------- --------------- --------------------
    03064           46              1
    03064           46              2
    03106           46              3
    03276           46              4
    03865           46              5
    83301           23              6
    83402           23              7
    83501           23              8
    83702           23              9
    83864           23              10

     

     

    如果想对输出的PostalCode进行排序,但是你打算先按照StateProvinceID进行分组,再排序。为了实现上述要求,我加入PARTITION BY子句,代码如下:

    12345678USE AdventureWorks2012;GOSELECT PostalCode, StateProvinceID,       ROW_NUMBER() OVER         (PARTITION BY StateProvinceID          ORDER BY PostalCode ASC) AS RowNumberFROM Person.AddressWHERE StateProvinceID IN (46,23);

     

    Code 8: 使用PARTITION BY 子句和ROW_NUMBER 函数查询

    运行结果如下:

    PostalCode      StateProvinceID RowNumber
    --------------- --------------- --------------------
    83301           23              1
    83402           23              2
    83501           23              3
    83702           23              4
    83864           23              5
    03064           46              1
    03064           46              2
    03106           46              3
    03276           46              4

    正如你看到的结果,通过添加分区子句,行数列RowNumber 每个不同的StateProvinceID 值都会从1重新开始排序。


    SQL中几个常用的排序函数

    标签:sql

    热心网友 时间:2022-04-10 03:16

    SELECT 业务员,SUM(数量)AS 总数量
    FROM 商品
    WHERE 商品='5'
    GROUP BY 业务员
    ORDER BY SUM(数量) DESC

    热心网友 时间:2022-04-10 04:34

    selet name from 表 where saleid=5 order by totalSale desc

    热心网友 时间:2022-04-10 06:09

    1楼正解
    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    ef英语哪个好 EF英孚英语培训怎么样? 英孚英语好不好 EF英孚教育到底好不好 大佬们,麦芒7和荣耀10那个值得入手?2500以下的机子还有啥好推荐的么... 介绍几款2500元以前的手机 像素一定要高 其他的不做要求 近期想入手一部安卓手机,价格2200到2500左右…买HTC desire Z还是 三星... 笔记本忘记开机密码怎么办急死了 笔记本电脑屏幕开机锁忘记密码 怎么办?急死了 华硕笔记本电脑开机密码忘记了怎样找回?系统是Windows 7旗舰版... 红楼梦读书笔记2000字,a是笔记不是感悟 红楼梦读书笔记 要2000字数、 要准确的、不要乱弄的、瞎填的、、急急... 鱼怎么蒸 清蒸鱼的做法 奔驰e200,配柏林之声音响吗 小柏林之声低音在哪 选装柏林之声有必要吗 柏林之声喇叭做成家庭音箱效果好吗? 求twitch破解下载 python 中的sort 方法不出结果啊 现在幼儿教师资格认定普通话二级乙等可以认定吗? 谁有好的办法,能把网上下载的图片上的水印去掉,要效果好方法比较简单 家庭财产保险的险种 普通话二乙算不算过啊,在线等 家庭财产保险属于什么保险 普通家财险保险标的 家庭财产保险有什么 家庭财产保险的主要内容 怎么用百度看微信小说 微信上搜小说会有记录吗 家庭财产保险是什么 我是商家,给客户开个人*和公司*有什么区别,我交的税一样吗 个人发票和公司发票有什么区别呢? 公司发票和个人发票有什么不同啊? 个人发票与单位发票的区别是什么?? 发票个人和单位的区别 请教 个人发票与单位发票的区别是什么?? 红蜻蜓哪里品牌? 对私开发票跟对公开发票有什么区别 红蜻蜓童装厂家是在哪个城市? 红蜻蜓西服什么档次 开发票有什么用?应该开公司还是个人?两者有什么区别吗? 香港红蜻蜓是哪里的品牌 谁知道红蜻蜓这牌子? 台湾红蜻蜓皮鞋是国际品牌吗,我怎么没听说过红蜻蜓是台湾的 红蜻蜓品牌实体店在哪里 红蜻蜓品牌的鞋子不错,有红蜻蜓这个牌子的服装吗? 红蜻蜓皮鞋在哪里可以买到正品! 幼儿园大班最新评语学习与发展综合分析怎么写? 幼儿园大班儿童发展评价怎么写 对大班幼儿发展观察及评价