sql server如何利用开窗函数over()进行分组统计

这是一道常见的面试题,在实际项目中经常会用到。

需求:求出以产品类别为分组,各个分组里价格最高的产品信息。

实现过程如下:

declare @t table(
ProductID int,
ProductName varchar(20),
ProductType varchar(20),
Price int)

--测试数据

insert @t
select 1,'name1','P1',3 union all
select 2,'name2','P1',5 union all
select 3,'name3','P2',4 union all
select 4,'name4','P2',4

--做法一:找到每个组里,价格最大的值;然后再找出每个组里价格等于这个值的
--缺点:要进行一次join

select t1.*
 from @t t1
 join (select ProductType,
  max(Price) Price
  from @t
  group by ProductType) t2 on t1.ProductType = t2.ProductType
 where t1.Price = t2.Price
 order by ProductType

--做法二:利用over(),将统计信息计算出来,然后直接筛选结果集。
--over() 可以让函数(包括聚合函数)与行一起输出。

;with cte as(
 select *, max(Price) over(partition by (ProductType)) MaxPrice
 from @t)
select ProductID,ProductName,ProductType,Price from cte where Price = MaxPrice
 order by ProductType

--over() 的语法为:over([patition by ] <order by >)。需要注意的是,over() 前面是一个函数,如果是聚合函数,那么order by 不能一起使用。
--over() 的另一常用情景是与 row_number() 一起用于分页。

现在来介绍一下开窗函数。

窗口函数OVER()指定一组行,开窗函数计算从窗口函数输出的结果集中各行的值。

开窗函数不需要使用GROUP BY就可以对数据进行分组,还可以同时返回基础行的列和聚合列。

1.排名开窗函数

ROW_NUMBER、DENSE_RANK、RANK、NTILE属于排名函数。

排名开窗函数可以单独使用ORDER BY 语句,也可以和PARTITION BY同时使用。

PARTITION BY用于将结果集进行分组,开窗函数应用于每一组。

ODER BY 指定排名开窗函数的顺序。在排名开窗函数中必须使用ORDER BY语句。

例如查询每个雇员的定单,并按时间排序

WITH OrderInfo AS

(

 SELECT ROW_NUMBER() OVER(PARTITION BY EmployeeID ORDER BY OrderDate) AS Number,

 OrderID,CustomerID, EmployeeID,OrderDate FROM Orders (NOLOCK)

)

SELECT Number,OrderID,CustomerID, EmployeeID ,OrderDate

From OrderInfo WHERE Number BETWEEN 0 AND 10

窗口函数根据PARTITION BY语句按雇员ID对数据行分组,然后按照ORDER BY 语句排序,排名函数ROW_NUMBER()为每一组的数据分从1开始生成一个序号。

ROW_NUMBER()为每一组的行按顺序生成一个唯一的序号

RANK()也为每一组的行生成一个序号,与ROW_NUMBER()不同的是如果按照ORDER BY的排序,如果有相同的值会生成相同的序号,并且接下来的序号是不连序的。例如两个相同的行生成序号3,那么接下来会生成序号5。

DENSE_RANK()和RANK()类似,不同的是如果有相同的序号,那么接下来的序号不会间断。也就是说如果两个相同的行生成序号3,那么接下来生成的序号还是4。

NTILE (integer_expression) 按照指定的数目将数据进行分组,并为每一组生成一个序号。

2.聚合开窗函数

很多聚合函数都可以用作窗口函数的运算,如SUM,AVG,MAX,MIN。

聚合开窗函数只能使用PARTITION BY子句或都不带任何语句,ORDER BY不能与聚合开窗函数一同使用。

例如,查询雇员的定单总数及定单信息

WITH OrderInfo AS

(

SELECT COUNT(OrderID) OVER(PARTITION BY EmployeeID) AS TotalCount,OrderID,CustomerID, EmployeeID,OrderDate FROM Orders (NOLOCK)

)

SELECT OrderID,CustomerID, EmployeeID ,OrderDate,TotalCount

From OrderInfo ORDER BY EmployeeID

如果窗口函数不使用PARTITION BY 语句的话,那么就是不对数据进行分组,聚合函数计算所有的行的值。

WITH OrderInfo AS

(

 SELECT COUNT(OrderID) OVER() AS Count,OrderID,CustomerID, EmployeeID,OrderDate FROM Orders (NOLOCK)

)

以上就是本文的全部内容,希望大家可以学会sql server利用开窗函数进行分组统计的方法,谢谢大家的阅读。

(0)

相关推荐

  • SQL Server 常用函数使用方法小结

    之前就想要把一些 SQL 的常用函数记录下来,不过一直没有实行...嘿嘿... 直到今天用到substring()这个函数,C# 里面这个方法起始值是 0,而 SQL 里面起始值是 1.傻傻分不清楚... 这篇博客作为记录 SQL 的函数的使用方法,想到哪里用到哪里就写到哪里... SubString():用于截取指定字符串的方法.该方法有三个参数: 参数1:用于指定要操作的字符串. 参数2:用于指定要截取的字符串的起始位置,起始值为 1 . 参数3:用于指定要截取的长度. select sub

  • Sqlserver 自定义函数 Function使用介绍

    一.FUNCTION: 在sqlserver2008中有3中自定义函数:标量函数/内联表值函数/多语句表值函数,首先总结下他们语法的异同点: 同点: 1.创建定义是一样的: a, CREATE FUNCTION F_NAME(传入的参数名称 传入参数的类型) b,RETURNS 返回值类型 c,AS 异点:1.标量函数返回的是一个数据类型值,内联表值函数返回的是一个table,而多语句返回的是一个table的变量(类似前面两个的结合): 2.语法的结构:标量函数和多语句函数都是要有begin,,

  • Sql Server中REPLACE函数的使用

    REPLACE 用第三个表达式替换第一个字符串表达式中出现的所有第二个给定字符串表达式. 语法 REPLACE ( ''string_replace1'' , ''string_replace2'' , ''string_replace3'' ) 参数 ''string_replace1'' 待搜索的字符串表达式.string_replace1 可以是字符数据或二进制数据. ''string_replace2'' 待查找的字符串表达式.string_replace2 可以是字符数据或二进制数据.

  • SQL Server实现split函数分割字符串功能及用法示例

    本文实例讲述了SQL Server实现split函数分割字符串功能及用法.分享给大家供大家参考,具体如下: /* 函数名称:f_SplitToNvarchar 作用:实现split功能的函数 更新记录: 设计思路:将nvarchar类型字符结合的一个串,分隔到一张只有一列nvarchar类型的表里 */ CREATE FUNCTION [dbo].[f_SplitToNvarchar] ( @SourceSql NVARCHAR(MAX),--源分隔字符串 @StrSeprate VARCHAR

  • SQL server中字符串逗号分隔函数分享

    继SQl -Function创建函数数据库输出的结果用逗号隔开,在开发中也有许多以参数的形式传入带逗号字条串参数(数据大时不建议这样做) 例:查找姓名为"张三,李二" 的数据此时在数据库里就要对此参数做处理如图: 函数代码如下 CREATE FUNCTION [dbo].[fnSplitStr] ( @sText NVARCHAR(Max), @sDelim CHAR(1) ) RETURNS @retArray TABLE ( value VARCHAR(100) ) AS BEGI

  • sql server如何利用开窗函数over()进行分组统计

    这是一道常见的面试题,在实际项目中经常会用到. 需求:求出以产品类别为分组,各个分组里价格最高的产品信息. 实现过程如下: declare @t table( ProductID int, ProductName varchar(20), ProductType varchar(20), Price int) --测试数据 insert @t select 1,'name1','P1',3 union all select 2,'name2','P1',5 union all select 3,

  • SQL Server中的排名函数与分析函数详解

    一.排名开窗函数概述 SQL Server的排名函数是对查询的结果进行排名和分组,TSQL共有4个排名函数,分别是:ROW_NUMBER.RANK.DENSE_RANK和NTILE. 他们和OVER()函数搭配使用,按照特定的顺序排名. 排名开窗函数可以单独使用ORDER BY 语句,也可以和PARTITION BY同时使用. PARTITION BY用于将结果集进行分组,开窗函数应用于每一组. ODER BY 指定排名开窗函数的顺序.在排名开窗函数中必须使用ORDER BY语句. 1.ROW_

  • SQL Server中利用正则表达式替换字符串的方法

    建立正则替换函数,利用了OLE对象,以下是函数代码: --如果存在则删除原有函数 IF OBJECT_ID(N'dbo.RegexReplace') IS NOT NULL DROP FUNCTION dbo.RegexReplace GO --开始创建正则替换函数 CREATE FUNCTION dbo.RegexReplace ( @string VARCHAR(MAX), --被替换的字符串 @pattern VARCHAR(255), --替换模板 @replacestr VARCHAR

  • SQL Server创建用户定义函数

    一.UDF的定义 和存储过程很相似,用户自定义函数也是一组有序的T-SQL语句,UDF被预先优化和编译并且可以作为一个单元来进行调用. UDF和存储过程的主要区别在于返回结果的方式: 使用UDF时可传入参数,但不可传出参数.输出参数的概念被更为健壮的返回值取代了. 和系统函数一样,可以返回标量值,这个值的好处是它并不像在存储过程中那样只限于整形数据类型,而是可以返回大多数SQL Server数据类型. UDF有以下两种类型: 返回标量值的UDF. 返回表的UDF. 创建语法: CREATE FU

  • sql server数据库中raiserror函数用法的详细介绍

    sql server数据库中raiserror函数的用法 server数据库中raiserror的作用就和asp.NET中的throw new Exception一样,用于抛出一个异常或错误.这个错误可以被程序捕捉到. raiserror的常用格式如下: raiserror('错误的描述',错误的严重级别代码,错误的标识,错误的描述中的参数的值(这个可以是多个),一些其它参数),在官方上的格式描述如下: RAISERROR ( { msg_id | msg_str | @local_variab

  • SQL SERVER中常用日期函数的具体使用

    1 GETDATE() 返回当前系统日期 SELECT GETDATE() 2 DATEADD(日期部分,常数,日期) 返回将日期的指定日期部分加常数后的结果返回 常数为正 SELECT DATEADD(YY,1,GETDATE()) 等同于 SELECT DATEADD(YEAR,1,GETDATE()) 常数为负数 SELECT DATEADD(YY,-2,GETDATE()) 常数为小数(直接舍去小数部分) SELECT DATEADD(YY,2.4,GETDATE()) SELECT D

  • PHP操作SQL Server数据库实现表的改查与统计

    目录 今天上午做表格数据的检查与修改,涉及到PHP对MS SQL Server数据表的查询.统计与修改. 平时我也不记编码和命令,到了用的时候都再查手册,这往往很耗费时间,现在写博客有个好处就是把有用的代码记录下来,下次就直接复制,修改一下就直接用了. 这样可以省去很多时间. 下面是检索三个表来更新数据,即主表有信息不全,检索两个其他的信息表进行补录. <?php require 'pspLinkConfig.php';//加载数据库 $sql = "select C24 from cwk

  • SQL Server中的RAND函数的介绍和区间随机数值函数的实现

    工作中会遇到SQL Server模拟数据生成以及数值列值(如整型.日期和时间数据类型)随机填充等等任务,这些任务中都要使用到随机数.鉴于此,本文将对SQL Server中随机数的使用简单做个总结 . T-SQL 随机有关的三个函数 RAND([seed] 此函数生成从0到1之间随机 float 值(详细说明查看https://technet.microsoft.com/zh-cn/library/ms177610(v=sql.90).aspx). CHECKSUM ( * | expressio

  • SQL Server中日期时间函数的用法详解

    1.getdate():获取当前日期 返回当前SQLServer服务器所在计算机的日期和时间.返回值舍入到最近的秒小数部分,精度为.333秒数据库十七偏移量不包含在内. select getdate() --输出 2013-03-09 15:16:00.570 2.getutcdate():获取UTC时间值 select GETUTCDATE() -- 2013-06-18 08:02:53.253 3.year():获取年度信息 year函数以int数据类型的格式返回特定日期的年度信息.其中的

  • SQL Server中的文本函数和图像函数介绍

    1.查找特定字符串PATINDEX 语法与字符串的patindex一样. 2.获取文本指针TEXTPTR SQLServer在存储文本类型(ntext.text)和图像数据类型(image)时,默认情况是与常见的基本数据类型(如char.int等)这样的数据时单独存储的,也就是说,如果一个表中的字段有基本类型和图像文本类型,那么在输入数据时,基本类型和图像文件数据并不是保存在同一个页面上,而是分离存储的.分离存储后,那么基本类型数据和文本图像类型数据所在的页面就是通过文本指针建立联系,是一个16

随机推荐