如何使用OFFSET / FETCH不在行上但在行组上?

时间:2015-02-06 22:20:24

标签: sql-server grouping fetch offset

如果我有一对多的表格如下:

FamilyId          UserId
1                 1
1                 2
2                 3
2                 4
3                 5

我可以使用offset/fetch来获取一组行。但是我如何使用它来获得一系列家庭?我怎样才能fetch使用offset/fetch前两个系列(在这种情况下总共返回4行)?

3 个答案:

答案 0 :(得分:1)

正如评论中所述,您需要为不同的row number创建familyid,然后使用offset/fetch来过滤这些群组。

然后join已过滤的群组返回主表格以获取已过滤群组中的userid's

SELECT a.familyid,
       userid
FROM   yourtable a
       JOIN (SELECT Row_number()OVER(ORDER BY familyid)rn,
                    familyid
             FROM   (SELECT DISTINCT FamilyId
                     FROM   yourtable)b
             ORDER BY rn  OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY
            ) c
         ON a.FamilyId = c.FamilyId 

注意:这可以从sql server 2012+

开始

答案 1 :(得分:0)

我知道这是一个古老的问题,但是我碰到了这个问题,想使用DISTINCT和TOP提出更短,希望更优雅的解决方案。

SELECT *
FROM yourTable
WHERE FamilyId IN
     (SELECT DISTINCT TOP (2) FamilyId FROM yourTable)

另一种方法是使用DENSE_RANK函数,例如

SELECT FamilyId, UserId
FROM (SELECT DENSE_RANK() OVER (ORDER BY FamilyId) AS rn, FamilyId, UserId FROM yourTable) AS t
WHERE rn < 3

如果出于某种原因,必须强制使用OFFSET..FETCH,则以下解决方案是可行的,使用定义了要返回的记录数的变量:

DECLARE @intFamilyRowCnt INT 
SET @intFamilyRowCnt = 
    (
        SELECT COUNT(FamilyId) FROM yourTable WHERE FamilyId IN 
            (SELECT DISTINCT TOP (2) FamilyId FROM yourTable)
    )

SELECT * FROM yourTable
ORDER BY FamilyId
OFFSET 0 ROWS FETCH NEXT @intFamilyRowCnt ROWS ONLY

答案 2 :(得分:0)

您可以使用多个公用表表达式或表变量。希望以下内容能解决问题。

  1. 按您要唯一或选择不同值的数据分组

  2. 然后根据分页获取记录

  3. 加入原始表,然后返回数据。

    DECLARE 
        @PageSize INT = 2, 
        @PageNum  INT = 1,
        @YearId INT=2;
     DECLARE @userData TABLE([name] nvarchar(30) NOT NULL,[type] int not null)
    
    INSERT INTO @userData values ('u1', 1), ('u1', 2), ('u2', 1), ('u2', 2), ('u3', 1), ('u4', 1)
    
    ;WITH TempResult AS(
        SELECT distinct name as name FROM @userData
    )
    , UserResult AS (
        SELECT * FROM TempResult ORDER BY TempResult.name OFFSET (@PageNum-1)*@PageSize ROWS
        FETCH NEXT @PageSize ROWS ONLY
    ) SELECT ud.* FROM UserResult ur JOIN @userData ud on ur.name=ud.name