每个分类取最新的几条的SQL实现

分类统计时候,我们可能经常会碰到这样的需求,每个分类按照一定顺序,取几条数据,然后在一起显示。

这个问题的解决方法,我们通过搜索引擎,可以找到很多中。但是不是SQL语句过于复杂,就是在数据量比较大时候,性能特别成问题。

今天我就碰到这样一个需求。而我自己的解决方案就是SQL过于复杂,或者性能比较差的。为此我在CSDN论坛发了个帖子,看有没有更好的解决方案。

http://topic.csdn.net/u/20080504/14/5c5866c3-8b91-45ef-ab17-f994f88f8e42.html

CSDN的 SQL Server 板块  不愧是高手云集,问题发出不到半小时,就获得了近10种解决方案。经过测试,我把性能最高,且SQL不复杂的方案整理出来。特别感谢 jinjazz 的解答。

 

问题详细描述如下:

比如,假设我们有下面这样结构的一张表,这张表的数据量非常巨大。

CREATE TABLE table1
(
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](128) NOT NULL,
    [class] int not null,
    [date] datetime not null
)

class 表示分类编号。 分类数不固定, 至少有上千种分类 date 表示该条记录被更新的时间 我们现在想获得每个分类最新被更新的5条记录。

 

解决方案

select id,name,class,date from(
select id,name,class,date ,row_number() over(partition by class order by date desc)
as rowindex from table1) a
where rowindex <= 5

 

解决方案简单说明:

这个解决方案的关键就是使用了SQL 2005 的 ROW_NUMBER 这个全新的函数。

ROW_NUMBER ( ) 函数的语法如下: ROW_NUMBER ( )     OVER ( [ ] )

OVER 子句中的 PARTITION BY 将结果集分为多个分区。 OVER 子句中的 ORDER BY 将对 ROW_NUMBER 进行排序。

下面是MSDN的几个简单例子:

 

以下示例将根据年初至今的销售额,返回 AdventureWorks 中销售人员的 ROW_NUMBER。

USE AdventureWorks; 
GO 

SELECT c.FirstName, c.LastName ,
ROW_NUMBER() OVER(ORDER BY SalesYTD DESC) AS 'Row Number' ,s.SalesYTD, a.PostalCode 

FROM Sales.SalesPerson s INNER JOIN Person.Contact c ON s.SalesPersonID = c.ContactID 
INNER JOIN Person.Address a ON a.AddressID = c.ContactID 
WHERE TerritoryID IS NOT NULL AND SalesYTD <> 0; 

以下示例将返回行号为 50 到 60 的行(包含这两行),并按 OrderDate 进行排序。

USE AdventureWorks; 
GO 

WITH OrderedOrders AS ( SELECT SalesOrderID, OrderDate, 
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber' 
FROM Sales.SalesOrderHeader ) 

SELECT * FROM OrderedOrders WHERE RowNumber BETWEEN 50 AND 60; 

 

以下示例说明了如何使用 PARTITION BY 参数。

USE AdventureWorks; 
GO 

SELECT c.FirstName, c.LastName ,
ROW_NUMBER() OVER (PARTITION BY PostalCode ORDER BY SalesYTD DESC) AS 'Row Number' ,
s.SalesYTD, a.PostalCode 

FROM Sales.SalesPerson s INNER JOIN Person.Contact c ON s.SalesPersonID = c.ContactID 
INNER JOIN Person.Address a ON a.AddressID = c.ContactID 
WHERE TerritoryID IS NOT NULL AND SalesYTD <> 0; 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要从SQL Server一系列相似的表中几条数据,需要考虑以下几个因素: 1. 表的结构和命名:首先需要确认这一系列相似的表是否具有相同的表结构,即拥有相同的列名和数据类型。如果是相似但结构不同的表,则需要分别处理。 2. 数据需求和查询目的:确定需要从这一系列相似的表中几条数据的目的。是为了展示一个概览,还是为了分析统计数据等具体目的。 3. 数据量和性能需求:考虑这一系列相似的表的数据量大小以及查询性能的要求。如果数据量很大,可能需要对查询进行优化,以提高查询效率。 基于以上因素,可以采以下几种方法从这一系列相似的表中几条数据: 1. 使用TOP子句:可以使用TOP子句从每张表中出指定数量的数据。例如,如果需要从每张表中出前10条数据,可以使用以下语句: SELECT TOP 10 * FROM 表名; 2. 使用ROW_NUMBER()函数:可以使用ROW_NUMBER()函数对每张表的数据进行编号,然后使用WHERE子句筛选出指定编号范围的数据。例如,如果需要出每张表中的前10条数据,可以使用以下语句: SELECT * FROM ( SELECT *, ROW_NUMBER() OVER(ORDER BY 列名) AS RowNum FROM 表名 ) AS T WHERE T.RowNum <= 10; 3. 使用UNION ALL操作符:如果每张表的数据结构相同,可以使用UNION ALL操作符将每张表的数据合并为一个结果集。例如,如果需要出每张表中的前10条数据,可以使用以下语句: SELECT * FROM 表1 UNION ALL SELECT * FROM 表2 UNION ALL ... SELECT * FROM 表n ORDER BY 列名 LIMIT 10; 需要根据具体情况选择合适的方法,在保证查询性能的前提下,得所需的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值