CTE、ROW_NUMBER 和 ROWCOUNT

发布于 2024-12-05 08:32:33 字数 703 浏览 1 评论 0原文

我试图返回一页数据以及一个存储过程中所有数据的行数,如下所示:

WITH Props AS
(
    SELECT *,
    ROW_NUMBER() OVER (ORDER BY PropertyID) AS RowNumber
    FROM Property
    WHERE PropertyType = @PropertyType AND ...
)   

SELECT * FROM Props 
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 AND (@PageNumber * @PageSize);

我无法返回行数(最高行数)。

我知道这有已经讨论过(我见过这个: 从查询中获取 @@rowcount 的有效方法使用 row_number),但是当我在 CTE 中添加 COUNT(x) OVER(PARTITION BY 1) 时,性能会下降,并且上面通常不需要时间的查询会永远执行。我认为这是因为每行都计算计数?我似乎无法在另一个查询中重用 CTE。 Table Props 有 100k 条记录,CTE 返回 5k 条记录。

I am trying to return a page of data and also row count of all data in one stored procedure which looks like following:

WITH Props AS
(
    SELECT *,
    ROW_NUMBER() OVER (ORDER BY PropertyID) AS RowNumber
    FROM Property
    WHERE PropertyType = @PropertyType AND ...
)   

SELECT * FROM Props 
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 AND (@PageNumber * @PageSize);

I am unable to return the row count (highest row number).

I know this has already been discussed (I've seen this:
Efficient way of getting @@rowcount from a query using row_number) but when I add COUNT(x) OVER(PARTITION BY 1) in the CTE, the performance degrades and the query above that normally takes no time takes forever to execute. I reckon it's because the count is calculated for each row? I seems that I can't reuse the CTE in another query. Table Props has 100k records, CTE returns 5k records.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

酒绊 2024-12-12 08:32:33

应该

;WITH Props AS
(
    SELECT *,
        ROW_NUMBER() OVER (ORDER BY PropertyID) AS RowNumber
    FROM Property
    WHERE PropertyType = @PropertyType AND ...
)

, Props2 AS
(
    SELECT COUNT(*) CNT FROM Props
)

-- Now you can use even Props2.CNT
SELECT * FROM Props, Props2
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 AND (@PageNumber * @PageSize);

在 T-SQL 中,现在每一行都 有 CNT...或者您想要不同的东西?您想要第二个仅包含计数的结果集吗?那就做吧!

-- This could be the second result-set of your query.
SELECT COUNT(*) CNT
FROM Property
WHERE PropertyType = @PropertyType AND ...

注意:经过重新编辑,大卫现在引用的查询 1 已被删除,查询 2 现在是查询 1。

In T-SQL it should be

;WITH Props AS
(
    SELECT *,
        ROW_NUMBER() OVER (ORDER BY PropertyID) AS RowNumber
    FROM Property
    WHERE PropertyType = @PropertyType AND ...
)

, Props2 AS
(
    SELECT COUNT(*) CNT FROM Props
)

-- Now you can use even Props2.CNT
SELECT * FROM Props, Props2
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 AND (@PageNumber * @PageSize);

now you have CNT in every line... Or you wanted something different? You wanted a second resultset with only the count? Then do it!

-- This could be the second result-set of your query.
SELECT COUNT(*) CNT
FROM Property
WHERE PropertyType = @PropertyType AND ...

Note: reedited, the query 1 David was referencing now has been trashcanned, query 2 is now query 1.

金橙橙 2024-12-12 08:32:33

您想要整个结果集的计数,对吗?

这工作速度快吗?

SELECT *,(select MAX(RowNumber) from Props) as MaxRow 
FROM Props 
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 
    AND (@PageNumber * @PageSize);

You want the count for the whole resultset right?

does this work speedwise?

SELECT *,(select MAX(RowNumber) from Props) as MaxRow 
FROM Props 
WHERE RowNumber BETWEEN ((@PageNumber - 1) * @PageSize) + 1 
    AND (@PageNumber * @PageSize);
最好是你 2024-12-12 08:32:33

我遇到了同样的问题,想分享返回页面和总行数的代码。该问题已通过临时表解决。以下是存储过程的主体:

DECLARE @personsPageTable TABLE(
  RowNumber INT, 
  PersonId INT, 
  FirstName NVARCHAR(50), 
  LastName NVARCHAR(50), 
  BirthDate DATE, 
  TotalCount INT);
    
        ;WITH PersonPage AS 
        (
            SELECT 
                 ROW_NUMBER() OVER(ORDER BY persons.Id) RowNumber,
                 Id,
                 FirstName,
                 LastName,
                 BirthDate
            FROM Persons
            WHERE BirthDate >= @BirthDateFrom AND BirthDate <= @BirthDateTo
        ), TotalCount AS( SELECT COUNT(*) AS [Count] FROM PersonPage)
        INSERT INTO @personsPageTable
        SELECT *, (select * from TotalCount) TotalCount FROM PersonPage
        ORDER BY PersonPage.RowNumber ASC
        OFFSET ((@pageNumber - 1) * @pageSize) ROWS
        FETCH NEXT @pageSize ROWS ONLY
    
        SELECT TOP 1 TotalCount FROM @personsPageTable
    
        SELECT 
            PersonId, 
            FirstName, 
            LastName, 
            BirthDate
        FROM @personsPageTable

如您所见,我将 CTE 结果和总行数放入临时表中并选择两个查询。第一个返回总计数,第二个返回包含数据的页面。

I had the same problem and wanted to share the code which would return page and total rows. The problem is fixed by a temporary table. Here is the body of the stored procedure:

DECLARE @personsPageTable TABLE(
  RowNumber INT, 
  PersonId INT, 
  FirstName NVARCHAR(50), 
  LastName NVARCHAR(50), 
  BirthDate DATE, 
  TotalCount INT);
    
        ;WITH PersonPage AS 
        (
            SELECT 
                 ROW_NUMBER() OVER(ORDER BY persons.Id) RowNumber,
                 Id,
                 FirstName,
                 LastName,
                 BirthDate
            FROM Persons
            WHERE BirthDate >= @BirthDateFrom AND BirthDate <= @BirthDateTo
        ), TotalCount AS( SELECT COUNT(*) AS [Count] FROM PersonPage)
        INSERT INTO @personsPageTable
        SELECT *, (select * from TotalCount) TotalCount FROM PersonPage
        ORDER BY PersonPage.RowNumber ASC
        OFFSET ((@pageNumber - 1) * @pageSize) ROWS
        FETCH NEXT @pageSize ROWS ONLY
    
        SELECT TOP 1 TotalCount FROM @personsPageTable
    
        SELECT 
            PersonId, 
            FirstName, 
            LastName, 
            BirthDate
        FROM @personsPageTable

As you can see I put CTE result and total rows into the temporary table and select two queries. The first return total count and the second return page with data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文