SQL Server:带父子关系的偏移行获取下一步

时间:2018-10-28 15:43:50

标签: .net sql-server

我们目前使用分页网格来显示某些数据。为了完成分页,我们将start和count参数传入查询的OFFSET和FETCH NEXT部分的数据函数中。

通常,除了在数据中存在一对多关系的情况下,此方法有效。在这些情况下,我们(按预期)获得每个子属性的重复父行。使用Dapper,我们可以适当地将这些数据合并到对象中。

但是,问题是OFFSET和FETCH NEXT也考虑了这些子行。如果我们需要25条记录,则仅当那些父记录中的某些部分具有多个子记录时,我们才可以取回15条父记录。

典型示例:

SELECT C.Name, U.Make 
FROM Contacts C 
LEFT JOIN Units U on U.ContactId = C.ContactId 
OFFSET 10 FETCH NEXT 5 ROWS ONLY

可能的返回值:

 Name  | Make
 Tommy | Toyota
 Tommy | Nissan
 Bob   | Chevy
 Bob   | Ford
 Christie | Chevy

正如人们所看到的,即使总记录集是请求的5个项目,我们也只能取回3个父记录。

是否存在一种构造查询的方法,使得OFFSET和FETCH NEXT仅适用于父表/记录,而不会仅仅通过仅获取父记录和正在运行的查询来填充子属性来强行执行此操作?

蛮力示例:

var contacts = queryToGetParentRecords(); foreach(var contact in contacts){ contact.CarMakes = queryToGetChildData(contact.Id); }

1 个答案:

答案 0 :(得分:1)

由于在SQL表中没有顺序,因此您需要在SQL中使用ORDER BY才能使用FETCH。

我会出于您的目的使用窗口功能。如果您通过ContactId订购,则类似以下内容。您需要使用CTE或子查询来利用density_rank结果:

;with cte as (

    SELECT 
         C.Name, U.Make 
        ,dense_rank() over (order by C.ContactId) FetchRank
        FROM Contacts C 
        LEFT JOIN Units U
        ON U.ContactId = C.ContactId 

)
select Name, Make
    from cte
    where FetchRank between 10 and 15