我整个周末都在和这个问题作斗争,毫无头绪。为了在我的网站上的搜索结果页面,我需要从SQL Server 2005 Express数据库返回行子集(即在第20行开始,给我接下来的20条记录)。在MySQL中,你可以使用"LIMIT"关键字来选择从哪一行开始以及返回多少行。
在SQL Server我发现ROW_NUMBER()/OVER,但当我尝试使用它时,它说"OVER不支持"。我认为这是因为我使用SQL Server 2005 Express(免费版)。有人能证实这是真的吗?或者是否有其他原因导致OVER子句不被支持?
然后我发现旧版本类似于:
SELECT TOP X * FROM TABLE WHERE ID NOT IN (SELECT TOP Y ID FROM TABLE ORDER BY ID) ORDER BY ID
,其中X=每页数,Y=从哪条记录开始
然而,我的查询要复杂得多,有许多外部连接,有时还会按主表以外的东西排序。例如,如果有人选择按用户发布的视频数量排序,查询可能需要像这样:
SELECT TOP 50 iUserID, iVideoCount FROM MyTable LEFT OUTER JOIN (SELECT count(iVideoID) AS iVideoCount, iUserID FROM VideoTable GROUP BY iUserID) as TempVidTable ON MyTable.iUserID = TempVidTable.iUserID WHERE iUserID NOT IN (SELECT TOP 100 iUserID, iVideoCount FROM MyTable LEFT OUTER JOIN (SELECT count(iVideoID) AS iVideoCount, iUserID FROM VideoTable GROUP BY iUserID) as TempVidTable ON MyTable.iUserID = TempVidTable.iUserID ORDER BY iVideoCount) ORDER BY iVideoCount
问题是在子查询 SELECT line: TOP 100 iUserID, iVideoCount
要使用"NOT IN"子句,似乎我只能在子查询("SELECT TOP 100 iUserID FROM…")中有1列。但当我没有在子查询SELECT语句中包含iVideoCount时子查询中的ORDER BY iVideoCount排序不正确因此子查询的排序与父查询不同,这就没用了。还有大约5个表通过外连接连接在一起,可以在排序中发挥作用。
我很茫然!上述两种方法是我能找到的唯一两种方法,让SQL Server返回行子集。我准备返回整个结果,并通过PHP中的每条记录循环,但只显示我想要的记录。这是一种效率低下的方法,是我最后的选择。
关于如何使SQL Server在上述场景中模仿MySQL的LIMIT子句的任何想法?
不幸的是,虽然SQL Server 2005的Row_Number()可以用于分页,SQL Server 2012的数据分页支持增强了Order By Offset和Fetch Next,如果你不能使用这些解决方案,你需要首先
- 创建一个包含identity列的临时表。
- 然后用ORDER BY子句 将数据插入临时表
- 使用临时表的标识列值,就像ROW_NUMBER()值一样
我希望它有帮助,