我正在尝试在SQL Server中的存储过程中进行分页,如下所示:
/*Assign a row number to each row*/
SELECT
ROW_NUMBER() OVER (ORDER BY A, B, C ASC) AS ROW_NUMBER,
A, B, C
FROM ABC
WHERE ROW_NUMBER BETWEEN @startRecordNumber and @endRecordNumber
但是,我的调用代码也想知道在分页之前原始结果集中有多少结果。所以,我将我的代码更改为:
/*Put the results into a temp table first*/
SELECT
ROW_NUMBER() OVER (ORDER BY A, B, C ASC) AS ROW_NUMBER,
A, B, C
INTO #TOTAL_RESULTS
FROM ABC
/*Get the total results from @@RowCount*/
declare @totalResults bigint
set @totalResults = @@RowCount
/*Now just get the desired page from the temp table*/
SELECT
A, B, C
FROM #TOTAL_RESULTS
WHERE ROW_NUMBER BETWEEN @startRecordNumber and @endRecordNumber
DROP TABLE #TOTAL_RESULTS
这对我来说非常迂回。有没有办法获得原始结果集的大小而不必制作临时表?也许只是一个公用表表达式?我似乎无法想办法做到这一点。
如果重要,这是ABC的架构:
ABC
A(PK,smallint not null)
B(PK,smallint not null)
C(PK,smallint not null)
答案 0 :(得分:3)
您可以使用窗口聚合函数。即COUNT(*) OVER()
以下示例。
;WITH cte As
(
SELECT *,
ROW_NUMBER() OVER (ORDER BY number) AS RN,
COUNT(*) OVER() AS Cnt
FROM master..spt_values
)
SELECT *
FROM cte
WHERE RN BETWEEN 101 and 200
或者 - 不是一个严肃的建议,但确实避免了线轴,工作台和双重排序: - )
DECLARE @Spid INT = @@Spid
DECLARE @TraceID INT
DECLARE @maxfilesize BIGINT = 5
DECLARE @filepath NVARCHAR(200) = N'C:\trace_' + LEFT(NEWID(),36)
EXEC sp_trace_create @TraceID OUTPUT, 0, @filepath, @maxfilesize, NULL
exec sp_trace_setevent @TraceID, 146, 1, 1
exec sp_trace_setevent @TraceID, 146, 22, 1
exec sp_trace_setevent @TraceID, 146, 34, 1
exec sp_trace_setevent @TraceID, 146, 51, 1
exec sp_trace_setevent @TraceID, 146, 12, 1
-- filter for spid
EXEC sp_trace_setfilter @TraceID, 12, 0, 0, @Spid
-- start the trace
EXEC sp_trace_setstatus @TraceID, 1
;WITH cte AS
(
SELECT number, type, name,
ROW_NUMBER() OVER (ORDER BY number, type, name) AS RN
FROM master..spt_values
)
SELECT * FROM cte
WHERE RN BETWEEN 101 AND 200
OR RN+1 =0 /*To stop a "TOP 200" getting added to the plan*/
;WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql)
SELECT ActualRows
FROM fn_trace_getinfo(@TraceID) fn
CROSS APPLY fn_trace_gettable(CAST(value AS NVARCHAR(200)), 1)
CROSS APPLY (SELECT CAST(TextData AS XML) AS xPlan) x
CROSS APPLY (SELECT T.relop.value('@ActualRows', 'INT') AS ActualRows
FROM xPlan.nodes('//sql:RelOp[@LogicalOp="Segment"]/sql:RunTimeInformation/sql:RunTimeCountersPerThread') T(relop)) ca
WHERE property = 2
AND ObjectName<>'fn_trace_getinfo' AND TextData NOT LIKE '%ThisQuery%'
-- Stop the trace
EXEC sp_trace_setstatus @TraceID, 0
-- Close and delete the trace
EXEC sp_trace_setstatus @TraceID, 2
答案 1 :(得分:3)
据我所知,不可能同时返回行并与SQL Server一起分配变量。因此,如果您希望将行计数存储到变量中,则必须以某种方式拥有多个语句。
但是,如果可以将总数作为一列返回并且如果A,B和B中的表中没有重复项就可以了。 C列,你可以返回总数,例如,像这样:
SELECT
A, B, C,
TotalResults = RowNumAsc + RowNumDesc - 1
FROM (
SELECT
A, B, C,
RowNumAsc = ROW_NUMBER() OVER (ORDER BY A, B, C),
RowNumDesc = ROW_NUMBER() OVER (ORDER BY A DESC, B DESC, C DESC)
FROM
) s
WHERE RowNumAsc BETWEEN @startRecordNumber AND @endRecordNumber