Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 游标/递归是这里唯一可能的选项吗?基于特定滞后条件的集合逻辑_Sql_Sql Server - Fatal编程技术网

Sql 游标/递归是这里唯一可能的选项吗?基于特定滞后条件的集合逻辑

Sql 游标/递归是这里唯一可能的选项吗?基于特定滞后条件的集合逻辑,sql,sql-server,Sql,Sql Server,我使用的是SQL Server,我有一个包含3列timeseries数据的表,其中包含日期、小时开始时间和获奖状态 大部分的奖励状态是随机生成的。有两种选择,授予或不授予 但是,业务要求是,如果状态为NotAwarded,我们必须连续打印3行“NotAwarded”,如果状态为Deward,则必须连续打印4行 目标:一个新的专栏应该是详细信息 一旦满足最低要求,它将检查当前行的AwardStatus并继续覆盖逻辑 问:在SQL中,没有任何类型的游标/循环,这可能吗 下面的图片是一个例子 下面是一

我使用的是SQL Server,我有一个包含3列timeseries数据的表,其中包含日期、小时开始时间和获奖状态

大部分的奖励状态是随机生成的。有两种选择,授予或不授予

但是,业务要求是,如果状态为NotAwarded,我们必须连续打印3行“NotAwarded”,如果状态为Deward,则必须连续打印4行

目标:一个新的专栏应该是详细信息

一旦满足最低要求,它将检查当前行的AwardStatus并继续覆盖逻辑

问:在SQL中,没有任何类型的游标/循环,这可能吗

下面的图片是一个例子

下面是一个例子:

AwardStatusMinimum  3       
AwardStatusMaximum  4       

Date    Hour    AwardStatus ShouldBe
--------------------------------------
1/1/2019    1   NotAwarded  NotAwarded
1/1/2019    2   NotAwarded  NotAwarded
1/1/2019    3   Awarded     NotAwarded
1/1/2019    4   Awarded     Awarded
1/1/2019    5   NotAwarded  Awarded
1/1/2019    6   NotAwarded  Awarded
1/1/2019    7   Awarded     Awarded
1/1/2019    8   NotAwarded  NotAwarded
1/1/2019    9   Awarded     NotAwarded
1/1/2019    10  Awarded     NotAwarded

这使您无需使用光标即可完成此操作

 declare @date date
 declare @hour int
 declare @CurrentStatus varchar(50)

 set @CurrentStatus=''

 while exists(select * from Awards where ShouldBe is null)
 begin
     select top 1 @date=[date], @hour=[hour] , @CurrentStatus=AwardStatus
     from Awards 
     where [ShouldBe] is null 
     order by [date],[hour]

     if(@CurrentStatus='Awarded')
     begin
         update top(4) Awards
         set ShouldBe=@CurrentStatus
         where [date]=@date and [hour]>=@hour
     end
     else 
         begin
         update top(3) Awards
         set ShouldBe=@CurrentStatus
         where [date]=@date and [hour]>=@hour
     end

 end

因为提到了递归

这里有一个使用递归CTE的解决方案

样本数据:

查询:


dbfiddle上的一个测试

嗨,欢迎来到SO。没有图片链接,请键入数据示例和模式以帮助我们。看,对不起!新这里,刚刚添加了代码文本!!我认为这可能是你问题的解决方案,我们希望这样:在原始帖子中添加,谢谢horaciux,这将确保这就是我今后提问的方式。
CREATE TABLE Table1 (
  [Date] DATETIME NOT NULL, 
  [Hour] INT NOT NULL, 
  [AwardStatus] VARCHAR(10)
);

INSERT INTO Table1
 ([Date], [Hour], [AwardStatus])
VALUES
 ('2019-01-01', 1, 'NotAwarded'),      
 ('2019-01-01', 2, 'NotAwarded'),     
 ('2019-01-01', 3, 'Awarded'),
 ('2019-01-01', 4, 'Awarded'),
 ('2019-01-01', 5, 'NotAwarded'),
 ('2019-01-01', 6, 'NotAwarded'),
 ('2019-01-01', 7, 'Awarded'),
 ('2019-01-01', 8, 'NotAwarded'),
 ('2019-01-01', 9, 'Awarded'),
 ('2019-01-01', 10, 'Awarded');
;with CTE_DATA AS 
(
  select *
  , dense_rank() 
    over (order by cast([Date] as date)) as grp
  , row_number() 
    over (partition by cast([Date] as date) order by [Hour]) as rn
  from Table1
)
, RCTE_AWARDS as
(
  select [Date], [Hour]
  , AwardStatus
  , grp
  , rn
  , 1 as Lvl
  , AwardStatus AS CalcStatus
  from CTE_DATA
  where rn = 1
  
  union all
  
  select t.[Date], t.[Hour]
  , t.AwardStatus
  , t.grp
  , t.rn
  , case
    when (c.lvl < 3)
      or (c.lvl < 4 and c.CalcStatus = 'Awarded')
    then c.lvl+1
    else 1
    end
  , case 
    when (c.lvl = 3 and c.CalcStatus = 'NotAwarded')
      or (c.lvl = 4)
    then t.AwardStatus
    else c.CalcStatus
    end
  from RCTE_AWARDS c
  join CTE_DATA t 
    on t.grp = c.grp
   and t.rn = c.rn + 1
)
select [Date], [Hour], AwardStatus
, CalcStatus AS NewAwardStatus
from RCTE_AWARDS
order by [Date], [Hour]

GO
Date | Hour | AwardStatus | NewAwardStatus :---------------------- | ---: | :---------- | :------------- 2019-01-01 00:00:00.000 | 1 | NotAwarded | NotAwarded 2019-01-01 00:00:00.000 | 2 | NotAwarded | NotAwarded 2019-01-01 00:00:00.000 | 3 | Awarded | NotAwarded 2019-01-01 00:00:00.000 | 4 | Awarded | Awarded 2019-01-01 00:00:00.000 | 5 | NotAwarded | Awarded 2019-01-01 00:00:00.000 | 6 | NotAwarded | Awarded 2019-01-01 00:00:00.000 | 7 | Awarded | Awarded 2019-01-01 00:00:00.000 | 8 | NotAwarded | NotAwarded 2019-01-01 00:00:00.000 | 9 | Awarded | NotAwarded 2019-01-01 00:00:00.000 | 10 | Awarded | NotAwarded