使用其他列生成新列

时间:2011-05-17 20:16:46

标签: tsql

我坚持要生成一个新列。该表有三列(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

我想生成另一个名为Cycle的列,对于每个C_ID,它应该从一个开始生成数字并从下一个C_rank = 'A'增加数字(a如上所示)。

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

可能有一些循环选项直到下一个C_Rank = 'A'有效。

如何做到这一点?

4 个答案:

答案 0 :(得分: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_NUMBERC_ID,C_Rank的每个不同值再次从1开始 - 我不知道单个分区中的ORDER BY子句(您正在寻找的单个值C_ID,C_Rank),并且猜测它可能是Date DESC(最新的日期优先)。

答案 1 :(得分: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.

答案 2 :(得分: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

答案 3 :(得分: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