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

ここにいくつかの解決策があります-1つは単純で、もう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

これは機能するはずです。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 に答える
0

最後のコメントへの返信が遅くなってすみません。私は週末の初めに仕事/離れていました。私の以前の答えに基づいてあなたが求めていることは達成できますが、以下のコードははるかに効率的で読みやすいと思います。以下のコードの欠点は、これが新しいSQL2012LAGおよびLEAD機能に依存していることです。

これらの機能については、http: //blog.sqlauthority.com/2011/11/15/sql-server-introduction-to-lead-and-lag-analytic-functions-introduced-in-sql-serverで確認できます。-2012 /

アップグレードを選択した場合のSQL2012ライセンスに関する情報: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 に答える