如何在SQL Server 2008中保留和增加变量的值?

时间:2012-08-05 06:55:42

标签: sql-server-2008

最初,我有两个变量x(组变量)和y,现在我想创建第三个变量z,每个x组中的每个从1开始,每当y变化时增加1。请参阅以下示例。有人可以帮助我在sql server 2008中实现它吗?

非常感谢!

x: a a a a a a a a b b b b b b b b
y: 0 0 0 1 0 0 2 3 0 1 0 0 2 3 0 0

最后,我想像这样创建z:

x: a a a a a a a a b b b b b b b b
y: 0 0 0 1 0 0 2 3 0 1 0 0 2 3 0 0
z: 1 1 1 2 3 3 4 5 1 2 3 3 4 5 6 6

4 个答案:

答案 0 :(得分:3)

您可以使用recursive CTErow_number之类的内容。

with C1 as
(
  select T1.id,
         T1.x,
         T1.y,
         row_number() over (partition by T1.x order by T1.id) as rn
  from table1 as T1
), C2 as
(
  select C1.id,
         C1.x,
         C1.y,
         C1.rn,
         1 as z
  from C1
  where C1.rn = 1
  union all
  select C1.id,
         C1.x,
         C1.y,
         C1.rn,
         C2.z + case when C1.y <> C2.y then 1 else 0 end
  from C1 
    inner join C2
      on C1.x = C2.x and
         C1.rn = C2.rn + 1
)
select x, y, z
from C2
order by id
option (maxrecursion 0);

请注意,使用CTE作为递归查询的源可能会遇到一些性能问题。如果是这种情况,我建议您将CTE C1的结果放在(x, rn)上带有主键的临时表中。

SQL Fiddle

答案 1 :(得分:1)

您无法使用row_number() over (partition by ... order by ...)执行此操作,CTE查询似乎也无效。我希望尽可能避免使用游标,但光标可能适合您的情况:

declare @tbl table (id int, x char(1), y int, z int null)

declare
  @id int, @x char(1), @y int,
  @x2 char(1) = null, @y2 int = null, @z int

insert into @tbl (id, x, y) values
(1, 'a', 0), (2, 'a', 0), (3, 'a', 0),
(4, 'a', 1),
(5, 'a', 0), (6, 'a', 0),
(7, 'a', 2),
(8, 'a', 3),
(9, 'b', 0),
(10, 'b', 1),
(11, 'b', 0), (12, 'b', 0),
(13, 'b', 2),
(14, 'b', 3),
(15, 'b', 0), (16, 'b', 0)

declare cr cursor for
  select id, x, y
  from   @tbl
  order by  id

open cr
fetch next from cr into @id, @x, @y

while @@fetch_status = 0
begin
  set @z =
    case when @x2 is null or @x <> @x2
      then 1
      else
        case when @y = @y2
          then @z
          else @z + 1
        end
    end

  update @tbl
  set    z = @z
  where  id = @id

  set @x2 = @x
  set @y2 = @y

  fetch next from cr into @id, @x, @y
end

close cr
deallocate cr

select x, y, z
from   @tbl
order by id

答案 2 :(得分:1)

以为我会把我的解决方案投入到混合中:

declare @temp table ([row] int identity,[x] char,[y] int)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',1)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',2)
insert into @temp([x],[y]) values ('a',3)
insert into @temp([x],[y]) values ('b',0)
insert into @temp([x],[y]) values ('b',1)
insert into @temp([x],[y]) values ('b',0)
insert into @temp([x],[y]) values ('b',0)
insert into @temp([x],[y]) values ('b',2)
insert into @temp([x],[y]) values ('b',3)
insert into @temp([x],[y]) values ('b',0)
insert into @temp([x],[y]) values ('b',0)


declare @temp1 table
(
 [row] int
,[x] char
,[y] int
,[change] int
)
insert into @temp1
(
 [row]
,[x]
,[y]
,[change]
)
select 
 [t1].[row]
,[t1].[x]
,[t1].[y] 
,iif([t1].[x] = [t2].[x] and [t1].[y] <> [t2].[y],1,0) [change]
from @temp [t1]
left join @temp [t2] on [t2].[row] = [t1].[row] - 1

select * from @temp1

select 
 [row]
,[x]
,[y]
,(select sum([change]) from @temp1 [t2] where [t2].[row] <= [t1].[row] and [t2].[x] = [t1].[x]) + 1 [z]
from @temp1 [t1]

答案 3 :(得分:1)

这是一个简单的解决方案:

  declare @temp table ([row] int identity,[x] char,[y] int)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',1)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',0)
insert into @temp([x],[y]) values ('a',2)
insert into @temp([x],[y]) values ('a',3)
insert into @temp([x],[y]) values ('b',0)
insert into @temp([x],[y]) values ('b',1)
insert into @temp([x],[y]) values ('b',0)
insert into @temp([x],[y]) values ('b',0)
insert into @temp([x],[y]) values ('b',2)
insert into @temp([x],[y]) values ('b',3)
insert into @temp([x],[y]) values ('b',0)
insert into @temp([x],[y]) values ('b',0)

--select * from @temp 

DECLARE @int int=0
;WITH CTE as(
select *,1 as incr from @temp where row=1 
union all
select t.*,
CASE WHEN t.x=c.x then CASE WHEN t.y=c.y then incr else incr+1 end else CASE WHEN t.y=c.y then @int else @int+1 end end as incr
from @temp t inner join CTE c
on t.row=c.row+1
)

select * from CTE