1

当相邻行中的组名称发生变化时,我需要帮助生成序列号。我已经尝试过 DENSE RANK 但它没有用。

Group  ||  Sequence Number 
========================
  A    ||        1     7/1/2012
  A    ||        2     7/2/2012
  A    ||        3     7/2/2012
  B    ||        1     7/3/2012
  B    ||        2     7/3/2012
  B    ||        3     7/3/2012
  A    ||        1     7/4/2012
  A    ||        2     7/5/2012
  A    ||        3     7/5/2012
  C    ||        1
  B    ||        1  
  B    ||        2  
  C    ||        1  
  C    ||        2

谢谢

4

3 回答 3

1

这里有几个解决方案 - 一个简单,一个更复杂但更符合您的问题:

--if you want all As grouped first, then all Bs, etc
select *
, ROW_NUMBER() over (partition by [group] order by id) SequenceNumber
from demo

--if you want the more complex solution where the different groups of As are kept apart from one another
select id
, [group]
, ROW_NUMBER() over (partition by x.p order by x.id) sequenceNumber
from (
    select id
    , [group]
    , (
        select min(b.id)
        from demo b
        where b.[group] <> a.[group]
        and b.id > a.id
    ) p
    from demo a
) x
order by id

设置/运行上述示例的代码:

create table demo 
(
    id bigint identity(1,1) not null primary key clustered
    , [group] nchar not null
)
go
insert demo 
select 'A'
union all select 'A'
union all select 'A'
union all select 'B'
union all select 'B'
union all select 'B'
union all select 'C'
union all select 'C'
union all select 'C'
union all select 'A' --in your example you seemed to alow a second group of As separate to the first
union all select 'A' 
union all select 'A' 
union all select 'A' 
union all select 'C'
go
于 2012-08-03T00:17:54.077 回答
0

抱歉,您最后的评论回复缓慢;周末开始时我一直在工作/离开。你所追求的可以根据我之前的回答来实现,但我怀疑下面的代码会更有效率/可读性。以下代码的缺点是它确实依赖于新的 SQL 2012 LAG 和 LEAD 功能。

您可以在此处阅读这些功能:http: //blog.sqlauthority.com/2011/11/15/sql-server-introduction-to-lead-and-lag-analytic-functions-introduced-in-sql-server -2012/

如果您选择升级,请在此处了解有关 SQL 2012 许可的信息:http: //www.microsoft.com/sqlserver/en/us/get-sql-server/how-to-buy.aspx

显然,升级可能不合理的原因有很多,但我想我会提供这个答案,以防您/其他寻求此解决方案的人可以选择:

--Sample Data Setup:

    if object_id('demo') is not null drop table demo
    go
    create table demo 
    (
        id bigint identity(1,1) not null primary key clustered
        , groupId nchar not null
        , startDate date not null constraint uk_demo_startDate unique 
    )
    go
    insert demo 
    select 'A', '2009-01-01'
    union all select 'A', '2009-01-02'
    union all select 'A', '2009-02-01'
    union all select 'B', '2009-03-01'
    union all select 'B', '2009-04-01'
    union all select 'B', '2009-05-01'
    union all select 'C', '2009-06-01'
    union all select 'C', '2009-07-01'
    union all select 'C', '2009-08-01'
    union all select 'A', '2009-09-01'
    union all select 'A', '2009-10-01'
    union all select 'A', '2009-11-01'
    union all select 'A', '2009-12-01'
    union all select 'C', '2010-01-01'
    union all select 'D', '2010-01-02'
    union all select 'D', '2010-01-03'
    union all select 'D', '2010-01-04'
    union all select 'E', '2010-01-05'
    union all select 'E', '2010-01-06'
    union all select 'D', '2010-01-07'
    union all select 'D', '2010-01-08'
    union all select 'E', '2010-01-09'
    union all select 'E', '2010-01-10'
    union all select 'D', '2011-01-01'
    union all select 'D', '2011-01-02'
    union all select 'E', '2012-01-01'
    union all select 'X', '2012-01-02'
    union all select 'D', '2012-01-03'
    go

--Actual Solution
    select *
    , noDays + noDaysAtStatusAtStart noDaysAtStatusAtEnd
    from
    (
        select id
        , groupId
        , startDate
        , noDays 
        ,   case
                when groupId = previousGroupId then lag(noDays,1) over (order by startDate)
                --when previousGroupId is null then 0 --covered by else
                else 0
            end noDaysAtStatusAtStart
        from
        (
            select id
            , startDate
            , groupId
            , endDate
            , previousGroupId
            , dateDiff(day,startDate,endDate) noDays
            from
            (
                select id
                , startDate
                , groupId 
                , lead(startDate,1) over (order by startDate) endDate
                , lag(groupId,1) over (order by startDate) previousGroupId
                from demo
            ) x
        ) y
    ) z
    order by z.startDate
于 2012-08-05T17:30:54.087 回答
0

这应该工作,你可以做一个while循环。

declare @t table (
    id int identity primary key,
    yourgroup char,
    grouprank int
);
insert into @t (yourgroup)
select yourgroup
from yourtable;
declare @lastgroup char,
        @newrank int,
        @i int = (select MIN(id) from @t),
        @end int = (select MAX(id) from @t);
while @i <= @end begin
    if @lastgroup = (select yourgroup
                     from @t
                     where id = @i) begin
        set @newrank += 1;
    end else begin
        set @newrank = 1;
    end;

    select @lastgroup = yourgroup
    from @t
    where id = @i;

    update @t
    set grouprank = @newrank
    where id = @i;

    set @i += 1;
end;

select * from @t;
于 2012-08-03T00:20:37.273 回答