You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调整分页逻辑从视图获取指定数量唯一Ticket_Id的全量数据?

问题描述

我有一个返回Ticket_Id和Price两列的视图,每个工单最多对应2个不同的Price值。同时我有一个存储过程,通过以下分页参数返回视图数据:

@page     : 表示页码
@pageSize : 表示每页记录数

当用户请求100条唯一工单数据时,我需要返回最多200行数据(每个工单最多2条价格记录)。但当前使用的分页逻辑:

OFFSET ', @pageSize,' * (',@page,' - 1) ROWS 
    FETCH NEXT ', @pageSize,' ROWS ONLY 

只会返回包含重复Ticket_Id的100行数据,无法满足需求。请问如何修改分页参数来获取全部对应行?

示例

视图返回结果如下:

ticket_idprice
ticket110
ticket112
ticket211
ticket213
ticket312
ticket314

当传入参数@page = 1, @PageSize = 3时,需要返回全部6行数据(对应3个唯一工单的所有价格记录)。

视图定义

(因存储过程无法直接访问tickets表,故使用视图)

select 
    tck.ticket_id, tck.cost as 'price'
    --,RANK() OVER(ORDER BY tck.ticket_id) 'Rank'
from 
    tickets tck with (NOLOCK) 

存储过程定义

ALTER PROCEDURE [dbo].[p_trans_history_srch]
    @page      int = 1,     -- optional
    @pageSize  int = 20     -- optional
AS
BEGIN
    DECLARE @finalsqlstmt nvarchar(max)
    DECLARE @pageString nvarchar(max)
    DECLARE @pageCount nvarchar(max) = ''
    DECLARE @viewName nvarchar(max)

    SET @pageString = CONCAT(' OFFSET ', @pageSize,' * (',@page,' - 1) ROWS FETCH NEXT ', @pageSize,' ROWS ONLY')

    SET @finalsqlstmt = CONCAT('SELECT * FROM ', dbo.f_get_dbname(), @viewName, 'WHERE ',@search ,' AND created_date BETWEEN ''', @startDate, ''' AND ''', @endDate, ''' ORDER BY created_date DESC', @pageString)

    SET @pageCount = CONCAT('SELECT COUNT(DISTINCT ticket_id) FROM ', dbo.f_get_dbname(), @viewName, 'WHERE ', @search, ' AND created_date BETWEEN ''', @startDate, ''' AND ''', @endDate, '''')
    
    EXEC (@finalsqlstmt)
    EXEC (@pageCount)
END

注意事项

我曾尝试使用RANK() OVER(ORDER BY ticket_id) 'Rank'并基于排名返回数据,但因表数据量过大,查询性能骤降。


解决方案

核心思路是先对唯一工单进行分页,再关联视图获取所有对应价格记录,既保证分页逻辑按工单数量计算,又避免全表排序导致的性能问题。

修改存储过程中的@finalsqlstmt部分,替换为以下逻辑:

SET @finalsqlstmt = CONCAT(
    'WITH PaginatedTickets AS (',
        'SELECT DISTINCT ticket_id ',
        'FROM ', dbo.f_get_dbname(), @viewName, ' ',
        'WHERE ', @search, ' AND created_date BETWEEN ''', @startDate, ''' AND ''', @endDate, ''' ',
        'ORDER BY created_date DESC ',
        'OFFSET ', @pageSize, ' * (', @page, ' - 1) ROWS ',
        'FETCH NEXT ', @pageSize, ' ROWS ONLY ',
    ')',
    'SELECT v.* ',
    'FROM ', dbo.f_get_dbname(), @viewName, ' v ',
    'INNER JOIN PaginatedTickets pt ON v.ticket_id = pt.ticket_id ',
    'ORDER BY v.created_date DESC, v.ticket_id'
);

逻辑说明

  1. 分页筛选唯一工单:通过CTEPaginatedTickets先提取符合条件的唯一ticket_id,并按@page和@pageSize分页,这一步仅针对工单数量处理,数据量小,性能不受影响。
  2. 关联视图获取全量数据:将分页后的工单ID与原视图关联,取出每个工单对应的所有价格记录,最终返回行数为分页工单数量×最多2行,完全匹配需求。
  3. 保持排序一致性:最终结果按created_date DESC和ticket_id排序,与原逻辑输出顺序一致。

额外注意

  • 原存储过程中的@pageCount逻辑无需修改,它原本就是统计唯一工单数量,与新的分页逻辑完全匹配。
  • 若ticket_id和created_date存在联合索引,可进一步提升CTE部分的查询性能。

内容的提问来源于stack exchange,提问作者sandesh b n

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 20:10:30