循环遍历表中给定范围的每一行

时间:2021-03-02 18:41:29

标签: sql sql-server tsql

我有一个包含日期的表格

declare @x date ='01-jan-2021'
declare @y date ='31-jan-2021'
create table hdate( a date)
 
while @x <= @y
begin
    insert into hdate(a) values( @x)
    set @x = dateadd(day,1,@x)
end

如何遍历每条记录?

例如

declare @start_no int =1
declare @end_no int
select @end_no = count(*) from hdate where a between '05-jan-2021 and '10-jan-2020'
while @start_no <= @end_no
begin
    select a from hdate
    set @start_no = @start_no+1

    --how do I get next record?
end

预期结果是

a
05-jan-2021
06-jan-2021
07-jan-2021
08-jan-2021
09-jan-2021
10-jan-2021

我想使用while循环。请帮忙

4 个答案:

答案 0 :(得分:0)

不确定您为什么要使用循环,但我确定您有自己的理由......

-- 
-- option 1
--
declare @x date ='01-jan-2021'
declare @y date ='31-jan-2021'
declare @hdate table ( a date)

while @x<=@y
begin
insert into @hdate(a) values( @x)
set @x=dateadd(day,1,@x)
end


declare @i date 
declare @j date
select top 1 @i =  a from @hdate order by a
while @i is not null
    begin
    select @j = @i, @i = null


    select top 1 @i = a from @hdate where a > @j order by a
    select @j,@i

end

go

-- 
-- option 2
--
declare @x date ='01-jan-2021'
declare @y date ='31-jan-2021'
declare @hdate table ( a date, rowNum int identity)

while @x<=@y
begin
insert into @hdate(a) values( @x)
set @x=dateadd(day,1,@x)
end

select * from @hdate


declare @i int = 1
declare @j int 
select @j =  max(rowNum) from @hdate
while @i <= @j
    begin
    select * from @hdate where rowNum = @i
    select @i = @i + 1

end

go
-- 
-- option 3 -- no loop
--
declare @x date ='01-jan-2021'
declare @y date ='31-jan-2021'
declare @hdate table ( a date)

while @x<=@y
begin
insert into @hdate(a) values( @x)
set @x=dateadd(day,1,@x)
end

select * from @hdate


declare @i date = '01-jan-2021'

select h1.a as prev, x.a as next 
from @hdate h1
outer apply ( select top 1 h2.a from @hdate h2 where h2.a > h1.a) x
where h1.a = @i
order by h1.a

go

答案 1 :(得分:0)

Jim 展示了如何使用循环获得所需的结果,但指出循环不是可行的方法。在 SQL Server 中,执行此操作的正确方法是使用数字表或函数,例如 fnTally

declare @x date ='01-jan-2021'
declare @y date ='31-jan-2021'

SELECT SomeDate = DATEADD(DAY,f.N,@x) FROM dbo.fnTally(0,DATEDIFF(DAY,@x,@y)) AS f;

返回:

SomeDate
----------
2021-01-01
2021-01-02
2021-01-03
...
2021-01-29
2021-01-30
2021-01-31

用更少的代码更快、更高效。

答案 2 :(得分:0)

您可以使用 recursive CTE 创建连续值,这会在递归的每一步添加新项目。因此无需为此类任务编写命令式代码。

declare @x date = convert(date, '2021-01-01', 23);
declare @y date = convert(date, '2021-01-31', 23);

with a (dt) as (
  select @x
  where @x <= @y
  
  union all

  select dateadd(d, 1, dt)
  from a
  where dt < @y
)
insert into hdate(a)
select dt
from a

db<>fiddle here

答案 3 :(得分:0)

鉴于您的日期不是连续的,您可以使用:

declare @start_date datetime = '05-jan-2021'
declare @end_date datetime = '10-jan-2021'

declare @cdate datetime = @start_date

while (@cdate is not null or datediff(dd, @cdate, @end_date) >= 0)
begin

    select @cdate = min(a) from #hdate 
      where a between @cdate and @end_date

    if (@cdate is not null) 
    begin
        select a from #hdate
        where a = @cdate
    end

    select @cdate = dateadd(dd, 1, @cdate)

end