计算每一天 - 离工作日最近的天数
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];
看来您只需要将数据分组,然后 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
计算每一天 - 离工作日最近的天数。 可以限制提前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];
看来您只需要将数据分组,然后 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