2011-05-17 73 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