请问SQL Server 中是否有类似ORACLE 中分区函数patition by 的机能
现在有两个表article(文章) 和type(文章分类) 表结构如下
article:
1. id int(4)
2. name varchar2(10)
3. context ntext(200)
4. typeid int(4)
5. dateandtime smalldatetime(4)
type:
1.id int(4)
2.name varchar(10)
两个表通过article.typeid = type.id关联。现在想用1条sql检索 article中每个分类的最新三条记录。
例如;
Article
Id name context typeid dateandtime
1 test1 <long text> 1 2008/03/24 18:00:00
2 test2 <long text> 1 2008/03/24 18:01:00
3 test3 <long text> 2 2008/03/24 18:00:00
4 test4 <long text> 2 2008/03/24 18:02:00
5 test5 <long text> 2 2008/03/24 18:03:00
6 test6 <long text> 2 2008/03/24 18:04:00
Type
Id name
1国际新闻
2国内新闻
那么我需要的检索结果是
Test6 <long text> 国内新闻 2008/03/24 18:04:00
Test5 <long text> 国内新闻 2008/03/24 18:03:00
Test4 <long text> 国内新闻 2008/03/24 18:02:00
Test2 <long text> 国内新闻 2008/03/24 18:01:00
Test1 <long text> 国内新闻 2008/03/24 18:00:00
[解决办法]
select a.name,a.context,b.name,a.dateandtime from article a, type cwhere a.id in (select top 3 id from article b where a.typeid=b.typeid order by dateandtime desc)and a.typeid=b.typeid
[解决办法]
select m.name,m.context,n.name , m.dateandtime from( select t.* from article t where dateandtime in (select top 3 dateandtime from article where typeid = t.typeid order by dateandtime desc) ) m , type nwhere m.typeid = t.id
[解决办法]
create table article(id int,name varchar(10),context varchar(20),typeid int,dateandtime datetime)insert into article values(1 , 'test1', '<long text>', 1 , '2008/03/24 18:00:00') insert into article values(2 , 'test2', '<long text>', 1 , '2008/03/24 18:01:00') insert into article values(3 , 'test3', '<long text>', 2 , '2008/03/24 18:00:00') insert into article values(4 , 'test4', '<long text>', 2 , '2008/03/24 18:02:00') insert into article values(5 , 'test5', '<long text>', 2 , '2008/03/24 18:03:00') insert into article values(6 , 'test6', '<long text>', 2 , '2008/03/24 18:04:00')create table type(Id int , name varchar(10))insert into type values(1 ,'国际新闻') insert into type values(2 ,'国内新闻')goselect m.name,m.context,n.name , m.dateandtime from( select t.* from article t where dateandtime in (select top 3 dateandtime from article where typeid = t.typeid order by dateandtime desc) ) m , type nwhere m.typeid = n.iddrop table article, type/*name context name dateandtime ---------- -------------------- ---------- ------------------------------------------------------ test1 <long text> 国际新闻 2008-03-24 18:00:00.000test2 <long text> 国际新闻 2008-03-24 18:01:00.000test4 <long text> 国内新闻 2008-03-24 18:02:00.000test5 <long text> 国内新闻 2008-03-24 18:03:00.000test6 <long text> 国内新闻 2008-03-24 18:04:00.000(所影响的行数为 5 行)*/
[解决办法]
sql2005
select row_number() over (partition by a order by b)as row ,*from(select 'a' a,'b' b union select 'a','c' union select 'b','a')a/*row a b-------------------- ---- ----1 a b2 a c1 b a(3 行受影响)*/
[解决办法]
sql 2005的相关函数.
ROW_NUMBER、RANK、DENSE_RANK的用法(爱新觉罗.毓华 2007-12-16 广东深圳)SQL Server 2005 引入几个新的排序(排名)函数,如ROW_NUMBER、RANK、DENSE_RANK等。这些新函数使您可以有效地分析数据以及向查询的结果行提供排序值。 --------------------------------------ROW_NUMBER()说明:返回结果集分区内行的序列号,每个分区的第一行从 1 开始。语法:ROW_NUMBER () OVER ( [ <partition_by_clause> ] <order_by_clause> ) 。备注:ORDER BY 子句可确定在特定分区中为行分配唯一 ROW_NUMBER 的顺序。参数:<partition_by_clause> :将 FROM 子句生成的结果集划入应用了 ROW_NUMBER 函数的分区。 <order_by_clause>:确定将 ROW_NUMBER 值分配给分区中的行的顺序。返回类型:bigint 。示例:/*以下示例将根据年初至今的销售额,返回 AdventureWorks 中销售人员的 ROW_NUMBER。*/USE AdventureWorksGOSELECT c.FirstName, c.LastName, ROW_NUMBER() OVER(ORDER BY SalesYTD DESC) AS 'Row Number', s.SalesYTD, a.PostalCodeFROM Sales.SalesPerson s JOIN Person.Contact c on s.SalesPersonID = c.ContactIDJOIN Person.Address a ON a.AddressID = c.ContactIDWHERE TerritoryID IS NOT NULL AND SalesYTD <> 0/*FirstName LastName Row Number SalesYTD PostalCode--------- ---------- ---------- ------------ ----------------------------Shelley Dyck 1 5200475.2313 98027Gail Erickson 2 5015682.3752 98055Maciej Dusza 3 4557045.0459 98027Linda Ecoffey 4 3857163.6332 98027Mark Erickson 5 3827950.238 98055Terry Eminhizer 6 3587378.4257 98055Michael Emanuel 7 3189356.2465 98055Jauna Elson 8 3018725.4858 98055Carol Elliott 9 2811012.7151 98027Janeth Esteves 10 2241204.0424 98055Martha Espinoza 11 1931620.1835 98055Carla Eldridge 12 1764938.9859 98027Twanna Evans 13 1758385.926 98055(13 行受影响)*/ /*以下示例将返回行号为 50 到 60(含)的行,并以 OrderDate 排序。*/ USE AdventureWorks;GOWITH OrderedOrders AS(SELECT SalesOrderID, OrderDate,ROW_NUMBER() OVER (order by OrderDate)as RowNumberFROM Sales.SalesOrderHeader ) SELECT * FROM OrderedOrders WHERE RowNumber between 50 and 60;/*SalesOrderID OrderDate RowNumber------------ ----------------------- --------------------43708 2001-07-03 00:00:00.000 5043709 2001-07-03 00:00:00.000 5143710 2001-07-03 00:00:00.000 5243711 2001-07-04 00:00:00.000 5343712 2001-07-04 00:00:00.000 5443713 2001-07-05 00:00:00.000 5543714 2001-07-05 00:00:00.000 5643715 2001-07-05 00:00:00.000 5743716 2001-07-05 00:00:00.000 5843717 2001-07-05 00:00:00.000 5943718 2001-07-06 00:00:00.000 60(11 行受影响)*/--------------------------RANK()说明:返回结果集的分区内每行的排名。行的排名是相关行之前的排名数加一。语法:RANK () OVER ( [ < partition_by_clause > ] < order_by_clause > )备注:如果两个或多个行与一个排名关联,则每个关联行将得到相同的排名。 例如,如果两位顶尖销售员具有同样的 SalesYTD 值,他们将并列第一。 由于已有两行排名在前,所以具有下一个最大 SalesYTD 的销售人员将排名第三。 因此,RANK 函数并不总返回连续整数。 用于整个查询的排序顺序决定了行在结果集中的显示顺序。这也隐含了行在每个分区中的排名。参数:< partition_by_clause > :将 FROM 子句生成的结果集划分为要应用 RANK 函数的分区。 < order_by_clause >:确定将 RANK 值应用于分区中的行时所基于的顺序。返回类型:bigint示例:/*以下示例按照数量对清单中的产品进行了排名。行集按 LocationID 分区,按 Quantity 排序。USE AdventureWorks;GOSELECT i.ProductID, p.Name, i.LocationID, i.Quantity, RANK() OVER (PARTITION BY i.LocationID order by i.Quantity) as RANKFROM Production.ProductInventory i JOIN Production.Product p ON i.ProductID = p.ProductIDORDER BY p.NameGO/*ProductID Name LocationID Quantity RANK----------- -------------------------------------------------- ---------- -------- --------------------1 Adjustable Race 6 324 711 Adjustable Race 1 408 781 Adjustable Race 50 353 1172 Bearing Ball 6 318 672 Bearing Ball 1 427 852 Bearing Ball 50 364 1223 BB Ball Bearing 50 324 1063 BB Ball Bearing 1 585 1103 BB Ball Bearing 6 443 1154 Headset Ball Bearings 1 512 994 Headset Ball Bearings 6 422 1084 Headset Ball Bearings 50 388 140316 Blade 10 388 33......(1069 行受影响)*/ -------------------------------------------------
[解决办法]
DENSE_RANK()说明:返回结果集分区中行的排名,在排名中没有任何间断。行的排名等于所讨论行之前的所有排名数加一。语法:DENSE_RANK () OVER ( [ < partition_by_clause > ] < order_by_clause > )备注:如果有两个或多个行受同一个分区中排名的约束,则每个约束行将接收相同的排名。 例如,如果两位顶尖销售员具有相同的 SalesYTD 值,则他们将并列第一。 接下来 SalesYTD 最高的销售人员排名第二。该排名等于该行之前的所有行数加一。 因此,DENSE_RANK 函数返回的数字没有间断,并且始终具有连续的排名。 整个查询所用的排序顺序确定了各行在结果中的显示顺序。这说明排名第一的行可以不是分区中的第一行。参数:< partition_by_clause > :将 FROM 子句所生成的结果集划分为数个将应用 DENSE_RANK 函数的分区。 < order_by_clause >:确定将 DENSE_RANK 值应用于分区中各行的顺序。返回类型:bigint示例:/*以下示例返回各位置上产品数量的 DENSE_RANK。 */USE AdventureWorks;GOSELECT i.ProductID, p.Name, i.LocationID, i.Quantity, DENSE_RANK() OVER (PARTITION BY i.LocationID order by i.Quantity) as DENSE_RANKFROM Production.ProductInventory i JOIN Production.Product p ON i.ProductID = p.ProductIDORDER BY Name;GO/*ProductID Name LocationID Quantity DENSE_RANK----------- -------------------------------------------------- ---------- -------- --------------------1 Adjustable Race 1 408 571 Adjustable Race 6 324 521 Adjustable Race 50 353 82879 All-Purpose Bike Stand 7 144 34712 AWC Logo Cap 7 288 383 BB Ball Bearing 50 324 743 BB Ball Bearing 6 443 813 BB Ball Bearing 1 585 82*/-------------------------------------------------------------------将上面三个函数放在一起计算,更能明显看出各个函数的功能。CREATE TABLE rankorder(orderid INT,qty INT)INSERT rankorder VALUES(30001,10)INSERT rankorder VALUES(10001,10)INSERT rankorder VALUES(10006,10)INSERT rankorder VALUES(40005,10)INSERT rankorder VALUES(30003,15)INSERT rankorder VALUES(30004,20)INSERT rankorder VALUES(20002,20)INSERT rankorder VALUES(20001,20)INSERT rankorder VALUES(10005,30)INSERT rankorder VALUES(30007,30)INSERT rankorder VALUES(40001,40)INSERT rankorder VALUES(30007,30)GO--对一个列qty进行的排序SELECT orderid,qty, ROW_NUMBER() OVER(ORDER BY qty) AS rownumber, RANK() OVER(ORDER BY qty) AS rank, DENSE_RANK() OVER(ORDER BY qty) AS denserankFROM rankorderORDER BY qty/*orderid qty rownumber rank denserank----------- ----------- -------------------- -------------------- --------------------30001 10 1 1 110001 10 2 1 110006 10 3 1 140005 10 4 1 130003 15 5 5 230004 20 6 6 320002 20 7 6 320001 20 8 6 310005 30 9 9 430007 30 10 9 430007 30 11 9 440001 40 12 12 5(12 行受影响)*/ --对两个列qty,orderid进行的排序SELECT orderid,qty, ROW_NUMBER() OVER(ORDER BY qty,orderid) AS rownumber, RANK() OVER(ORDER BY qty,orderid) AS rank, DENSE_RANK() OVER(ORDER BY qty,orderid) AS denserankFROM rankorderORDER BY qty,orderiddrop table rankorder/*orderid qty rownumber rank denserank----------- ----------- -------------------- -------------------- --------------------10001 10 1 1 110006 10 2 2 230001 10 3 3 340005 10 4 4 430003 15 5 5 520001 20 6 6 620002 20 7 7 730004 20 8 8 810005 30 9 9 930007 30 10 10 1030007 30 11 10 1040001 40 12 12 11(12 行受影响)*/