代码之家  ›  专栏  ›  技术社区  ›  geographika

在SQL中使用窗口函数对Null记录进行分组

  •  2
  • geographika  · 技术社区  · 13 年前

    给定以下数据:

    declare @temp table(id int identity primary key, val nvarchar)
    
    insert into @temp values (NULL)
    insert into @temp values (NULL)
    insert into @temp values ('A')
    insert into @temp values (NULL)
    insert into @temp values (NULL)
    insert into @temp values ('B')
    insert into @temp values ('C')
    insert into @temp values (NULL)
    insert into @temp values (NULL)
    insert into @temp values ('A')
    insert into @temp values (NULL)
    insert into @temp values (NULL)
    

    我正在尝试获得下面的输出。需要对记录进行分组,以便每个新值的组号增加一个。值本身并不重要——如果存在NULL以外的任何值,则会添加一个新的组ID。记录必须按Id排序。

    Id Val  Group
    -- ---  -----
    1  NULL 1
    2  NULL 1
    3  A    2
    4  NULL 2
    5  NULL 2
    6  B    3
    7  C    4
    8  NULL 4
    9  NULL 4
    10 A    5
    11 NULL 5
    

    我希望使用PARTITION BY将是解决方案,但我似乎无法实现这一点(如果确实可能的话)。我有一个使用LOOP的解决方案,但是我更愿意使用查询。我使用的是SQL Server 2008。谢谢你的建议。

    select id, val, row_number() over (partition by X order by id) from @temp
    
    1 回复  |  直到 13 年前
        1
  •  2
  •   Gordon Linoff    13 年前

    这可以满足您的需求:

    select t.id, t.val, DENSE_RANK() over (order by prevval) as grouping
    from (select *,
                 (select top 1 id from @temp t2 where t2.val is not null and t2.id <= t.id order by id desc
                 ) as prevval
          from @temp t
         ) t
    

    这使用一个相关的子查询来获取小于或等于给定值的最大id,其中 val 不为null(如果有)。然后,它根据id对这些进行密集排序,以获得顺序分组。

    如果您使用的是SQL Server 2012,那么有一种相关的方法,没有子查询:

    select t.id, t.val, DENSE_RANK() over (order by prevval) as grouping
    from (select *,
                 max(case when val is not null then id end) over (order by id) as prevval
          from @temp t
         ) t