当相邻行中的组名更改时,我需要帮助生成序列号。我已经尝试过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
由于
答案 0 :(得分: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
答案 1 :(得分:0)
这应该有效,你可以做一段时间。
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;
答案 2 :(得分:0)
很抱歉您对上次评论的回复很慢;我一直在周末开始工作/离开。你可以根据我以前的答案实现你所追求的目标,但我怀疑下面的代码会更有效/可读。下面代码的缺点是它确实依赖于新的SQL 2012 LAG和LEAD功能。
有关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