2011-05-17 72 views
2

我被困在生成一个新列。该表有三列(C_ID,C_rank,Date)。使用其他列生成新列

C_ID C_ Rank NewColumn(Cycle) Date 
42  A  1   October 14, 2010 
42  B  1   October 26, 2010 
42  A  2   February 16, 2011 

43  A  1   December 17, 2010 

44  A  1   July 28, 2010 
44  B  1   August 10, 2010 
44  A  2   January 11, 2011 
44  B  2   January 28, 2011 

45  A  1   July 30, 2010 
45  B  1   August 9, 2010 
45  B  1   September 24, 2010 
45  A  2   April 5, 2011 
45  B  2   April 26, 2011 

我想以这样的方式,对于每个C_ID,它应产生从一个数开始并递增从下一个C_rank = 'A'(上面有示出)的数量,以产生一个称为Cycle多个列。

我试过使用row_number,但没有运气。

也许一些循环选项,直到下一个C_Rank = 'A'工程。

这怎么办?

+0

我一路跟随,直到'45组中的几行。 '45 B 1 2010年9月24日'。那个'1'不是'2'吗? “2011年4月26日的45 B 2”不应该是'3'吗? – 2011-05-17 20:22:16

回答

1

你应该能够开始使用ROW_NUMBER()PARTITION BY

;WITH YourDataCTE AS 
(
    SELECT 
     C_ID, C_Rank, Date, 
     ROW_NUMBER() OVER(PARTITION BY C_ID,C_Rank ORDER BY Date DESC) AS 'Cycle' 
    FROM 
     dbo.YourTable 
) 
SELECT * 
FROM YourDataCTE 

这是否你在寻找什么这个工作?

PARTITION BY C_ID,C_Rank将导致ROW_NUMBER在1再次启动的C_ID,C_Rank每个不同的价值 - 我不知道一个分区中的哪些条款ORDER BY(的C_ID,C_Rank单个值)你要找的,只是猜对了可能是Date DESC(最新的日期优先)。

+0

这会为'C_ID,Rank'组中的每一行分配越来越多的数字。不是什么问题要求 – Andomar 2011-05-17 20:36:01

+0

@Andomar:嗯....是的,似乎OP的要求是比这更复杂....不知道如何这项要求可以很容易地履行.... – 2011-05-17 20:37:52

1

你可以在子查询计数以前A的数量:

select * 
,  (
     select count(*) 
     from @YourTable yt2 
     where yt2.C_ID = yt1.C_ID 
       and yt2.C_Rank = 'A' 
       and yt2.Date <= yt1.Date 
     ) as Cycle 
from @YourTable yt1 
order by 
     C_ID, Date 

Example at ODATA.

0

做一个自我加入具有相同的C_ID,以前的日期的所有记录,以及C_Rank = 'A'并数它们。

select t1.C_ID, t1.C_Rank, count(t2.C_Rank) Cycle, t1.Date 
from MyTable t1 
    left join MyTable t2 on t1.C_ID=t2.C_ID 
         and t2.Date<=t1.Date 
         and t2.C_Rank='A' 
group by t1.C_ID, t1.C_Rank, t1.Date 
order by t1.C_ID, t1.Date 
+0

我使用类似的东西这个: – Punia 2011-05-18 17:34:51

+0

谢谢Chezy,你说得对,性能随着计数器而下降!您的代码也可以用更少的执行时间与我的requiremnt一起工作。谢谢 – Punia 2011-05-18 20:04:25

0

下面的代码符合要求:

create table #Temp_Table 
(
C_ID int 
, C_Rank char(1) 
, Date datetime 
, NewColumn int 
) 

insert into #Temp_Table 
(
C_ID 
, C_Rank 
, Date 
) 
select 42, ‘A’, ’10/14/2010′ 
union all 
select 42, ‘B’, ’10/26/2010′ 
union all 
select 42, ‘B’, ’10/14/2010′ 
union all 
select 42, ‘C’, ’10/26/2010′ 
union all 
select 42, ‘A’,’02/16/2011′ 
union all 
select 43, ‘A’, ’12/17/2010′ 
union all 
select 44, ‘A’, ’07/28/2010′ 
union all 
select 44, ‘B’, ’08/10/2010′ 
union all 
select 44, ‘A’, ’01/11/2011′ 
union all 
select 44, ‘B’, ’01/28/2011′ 
union all 
select 44, ‘C’, ’10/14/2010′ 
union all 
select 44, ‘D’, ’10/26/2010′ 

Select ‘Original Data’ Comment 
,* 
from #Temp_Table 

/* 
This would be Actual Script to get the New ID based on information you provided 
*/ 
Declare @Count int 
,@C_ID int 
,@C_Rank char(1) 
,@total_Count int 
,@Count_Partition int 
,@Previous_ID int 

Declare @Table Table (ID int IDENTITY(1,1), C_ID int, C_Rank char(1), Date datetime, NewColumn int) 

Set @Count = 1 
Set @Count_Partition = 0 

insert into @Table 
Select * 
from #Temp_Table 

Select @total_Count = ISNULL(MAX(ID),0) 
from @Table 

While @Count < = @total_Count 
Begin 
Select @C_ID = C_ID 
,@C_Rank = C_Rank 
From @Table 
Where ID = @Count 

If @Count = 1 
Set @Previous_ID = @C_ID 

If @Previous_ID != @C_ID 
Set @Count_Partition = 1 

Else If @C_Rank = 'A' 
Set @Count_Partition = @Count_Partition + 1 

update @Table 
Set NewColumn = @Count_Partition 
Where ID = @Count 

Set @Previous_ID = @C_ID 
Set @Count = @Count + 1 
End 

Select C_ID 
, C_Rank 
, [Date] 
, NewColumn 
from @Table 

–Drop table #Temp_Table 
+0

我使用计数器获得周期值。 – Punia 2011-05-18 17:37:12

+0

这样的循环应该在SQL中避免。试着在几千条记录上运行这个,你会明白我的意思。 – chezy525 2011-05-18 18:54:40