计算每一天 - 离工作日最近的天数

Count for each day - the number of days until the closer workday

计算每一天 - 离工作日最近的天数。 可以限制提前20天的天数。

DATE IS_HOLIDAY desirable result
05.01.2008 1 4
06.01.2008 1 3
07.01.2008 1 2
08.01.2008 1 1
09.01.2008 0 1
10.01.2008 0 1
11.01.2008 0 3
12.01.2008 1 2
13.01.2008 1 1
14.01.2008 0 1
15.01.2008 0 1
16.01.2008 0 1
17.01.2008 0 1

查询数据:

create table #tmp ( [date] date, is_holiday int )
insert into #tmp ( date, is_holiday )
select '2008-01-05' date, 1 is_holiday union 
select '2008-01-06' date, 1 is_holiday union 
select '2008-01-07' date, 1 is_holiday union 
select '2008-01-08' date, 1 is_holiday union 
select '2008-01-09' date, 0 is_holiday union 
select '2008-01-10' date, 0 is_holiday union 
select '2008-01-11' date, 0 is_holiday union 
select '2008-01-12' date, 1 is_holiday union 
select '2008-01-13' date, 1 is_holiday union 
select '2008-01-14' date, 0 is_holiday union 
select '2008-01-15' date, 0 is_holiday union 
select '2008-01-16' date, 0 is_holiday union 
select '2008-01-17' date, 0 is_holiday 

我试过使用这样的结构:

select date, sum(convert(int, is_holiday)) over (
    order by date
    rows between 5 preceding and current row
) as rsum
from dic_calendar_production

但它向后看。当我在 'following' 上更改 'preceding' 时,它会抛出错误

'BETWEEN ... FOLLOWING AND CURRENT ROW' is not a valid window frame and cannot be used with the OVER clause.

而且,它可以给我一些范围内的和,但是当它到达第一个零时它不会停止。

您可以使用 datediff:

的相关查询
select *, 
  IsNull(
    DateDiff(
    day, t.[date], 
      (select Min([date]) from #tmp t2 where t2.[date] > t.[date] and t2.is_holiday = 0)
  ),1) Result
from #tmp t
order by [date];

DB<>Fiddle example

看来您只需要将数据分组,然后 ROW_NUMBER:

create table #tmp ( [date] date, is_holiday int )
insert into #tmp ( date, is_holiday )
VALUES ('2008-01-05', 1),
       ('2008-01-06', 1),
       ('2008-01-07', 1),
       ('2008-01-08', 1),
       ('2008-01-09', 0),
       ('2008-01-10', 0),
       ('2008-01-11', 0),
       ('2008-01-12', 1),
       ('2008-01-13', 1),
       ('2008-01-14', 0),
       ('2008-01-15', 0),
       ('2008-01-16', 0),
       ('2008-01-17', 0);
GO
WITH CTE AS(
    SELECT [date],
           is_holiday,
           COUNT(CASE is_holiday WHEN 0 THEN 1 END) OVER (ORDER BY [date] ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING) AS Grp
    FROM #tmp t)
SELECT [date],
       is_holiday,
       ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY [date] DESC) AS desirableresult
FROM CTE
ORDER BY [date];

GO
DROP TABLE #tmp;
select t.date,t.is_holiday,isnull(app.date,t.date),isnull(DATEDIFF(day,t.date,app.date),1)diff
from #tmp t
cross apply
(
  select min(x.date) as date 
  from #tmp as x
  where t.date<x.date
 and x.is_holiday=0
)app

你也可以试试交叉apply-approach