相关博客:html
SQL中ROW_NUMBER和APPLY在处理TOP N等相似问题的一点比较服务器
有如下应用场景函数
row_number over语句:大数据
SELECT A.* FROM ( SELECT ROW_NUMBER() OVER (PARTITION BY O.employeeID ORDER BY O.orderdate DESC) AS ROW, E.LastName, E.FirstName, O.* FROM Employees E JOIN Orders O ON E.EmployeeID = O.EmployeeID) A WHERE A.ROW <= 2 ORDER BY A.EmployeeID;
这里是,先按employeeID分组再组内又按orderdate排序。用apply...top替换ui
SELECT E.FirstName, E.LastName, OT.* FROM Employees E CROSS APPLY ( SELECT TOP (2) * FROM Orders O WHERE O.EmployeeID = E.EmployeeID ORDER BY O.OrderDate DESC) AS OT ORDER BY E.EmployeeID;
能够用 EXCEPT 比较下两个查询语句得差别。若是没有输出,那么说明彻底是等价的。调试
当能够只须要输出一个聚合函数得值时,直接搞。例子以下:code
SELECT soh.SalesOrderID ,soh.OrderDate ,sod.max_unit_price FROM Sales.SalesOrderHeader AS soh JOIN ( SELECT max_unit_price = MAX(sod.UnitPrice), SalesOrderID FROM Sales.SalesOrderDetail AS sod GROUP BY sod.SalesOrderID ) sod ON sod.SalesOrderID = soh.SalesOrderID
这里是关联查询了另一张表 SalesOrderDetail,须要查出对应的UnitPrice得最大值。用apply...聚合函数直接替换。htm
SELECT soh.SalesOrderID ,soh.OrderDate ,sod.max_unit_price FROM Sales.SalesOrderHeader AS soh CROSS APPLY ( SELECT max_unit_price = MAX(sod.UnitPrice) FROM Sales.SalesOrderDetail AS sod WHERE soh.SalesOrderID = sod.SalesOrderID ) sod
那若是不是呢。
SELECT /*主外键*/ DISTINCT sale.WideGUID AS WideGUID, --业务GUID, s_room.RoomNo, s_room.Room AS RoomNum, s_room.UnitNo, s_room.FloorNo, s_room.HxName AS HxName, --户型 s_room.RoomStru AS RoomType, --房间类型 s_room.Unit AS Unit, --单元 s_room.FloorName AS Floor, --楼层· s_room.No AS No, --号码 s_room.RoomInfo AS RoomInfo, --房间全称 s_room.XxDate AS XxDate, --销许日期 s_room.JFDate AS SjjfDate, --实际交房日期 s_room.ShortRoomInfo AS ShortRoomInfo, --房间简称 s_room.FangPanUser AS FangPanUser, --放盘人 s_room.FangPanTime AS FangPanTime, --放盘时间 RoomControl.Reason AS FangPanReason --放盘批次 FROM ( SELECT DISTINCT s.WideGUID, s.RoomGUID FROM ( SELECT WideGUID, RoomGUID FROM s_Order WHERE OrderTypeEnum = 0 UNION ALL SELECT WideGUID, RoomGuid FROM s_Contract) s ) sale LEFT JOIN s_room ON s_room.RoomGUID = sale.RoomGUID LEFT JOIN ( SELECT s_RoomControl.RoomGUID, Reason FROM s_RoomControl INNER JOIN ( SELECT RoomGUID, MAX(ControlTime) ControlTime FROM s_RoomControl WHERE ControlType = 0 GROUP BY RoomGUID) T ON T.RoomGUID = s_RoomControl.RoomGUID AND T.ControlTime = s_RoomControl.ControlTime) RoomControl ON RoomControl.RoomGUID = s_room.RoomGUID
替换为:
SELECT /*主外键*/ sale.WideGUID AS WideGUID, --业务GUID, s_room.RoomNo, s_room.Room AS RoomNum, s_room.UnitNo, s_room.FloorNo, s_room.HxName AS HxName, --户型 s_room.RoomStru AS RoomType, --房间类型 s_room.Unit AS Unit, --单元 s_room.FloorName AS Floor, --楼层· s_room.No AS No, --号码 s_room.RoomInfo AS RoomInfo, --房间全称 s_room.XxDate AS XxDate, --销许日期 s_room.JFDate AS SjjfDate, --实际交房日期 s_room.ShortRoomInfo AS ShortRoomInfo, --房间简称 s_room.FangPanUser AS FangPanUser, --放盘人 s_room.FangPanTime AS FangPanTime, --放盘时间 RoomControl.Reason AS FangPanReason --放盘批次 FROM ( SELECT DISTINCT s.WideGUID, s.RoomGUID FROM ( SELECT WideGUID, RoomGUID FROM s_Order WHERE OrderTypeEnum = 0 UNION ALL SELECT WideGUID, RoomGuid FROM s_Contract) s ) sale LEFT JOIN s_room ON s_room.RoomGUID = sale.RoomGUID CROSS APPLY ( SELECT TOP 1 Reason FROM dbo.s_RoomControl WHERE dbo.s_RoomControl.RoomGUID = dbo.s_room.RoomGUID AND ControlType = 0 ORDER BY ControlTime DESC) RoomControl
为何会分析apply呢,主要是近期在工做中遇到大数据量状况下的分页查询,以及聚合查询,表的数据量原本就大,再这么一通操做,服务器直接扛不住。经过实践调试,最后发现apply能够解决这个问题,可是网上对这个apply也没过多的讲述,在这里也只是作个总结。最后的建议是,若是在大数据量下有分页查询或是链接大表又须要聚合查询,能够尝试apply得写法。能够用except来验证二者的输出。