在 SQL 服务器中保留今天日期的最后 n 个工作日记录

Keep last n business days records from today date in SQL Server

我们如何在这个 table:

中保留从今天开始的最后 n 个工作日的记录
Suppose n = 7

示例数据:

表 1:

Date
----------
2021-11-29
2021-11-30
2021-12-01
2021-12-02
2021-12-03
2021-12-04
2021-12-05
2021-12-06
2021-12-07
2021-12-08
2021-12-09
2021-12-10
2021-12-11
2021-12-12
2021-12-13

基于此 table 数据,我们希望输出如下所示。它应该删除 12 月 3 日之前的所有行或最近 7 个工作日的数据。

Date
-------
2021-12-03
2021-12-06
2021-12-07
2021-12-08
2021-12-09
2021-12-10
2021-12-13

注意:如果我们在工作日之间保留周六、周日的数据就可以了。

我试过这个查询

DECLARE @n INT = 7

SELECT * FROM Table1
WHERE  [date] < Dateadd(day, -((@n + (@n / 5) * 2)), Getdate())

但是周六、周日的逻辑不符合我的逻辑。请提出更好的方法。

您可以使用 CTE 标记目标日期,然后从 table 中删除所有其他日期,如下所示:

; With CTE As (
Select [Date], Row_number() Over (Order by [Date] Desc) As Num
From tbl 
Where DATEPART(weekday, [Date]) Not In (6,7)
)
Delete From tbl
Where [Date] Not In (Select [Date] From CTE Where Num<=7)

如果 table 中的工作日可能少于 7 天,您需要通过添加休息日使总天数达到 7 天,试试这个:

Declare @n Int = 7

; With CTE As (
Select [Date], IIF(DATEPART(weekday, [Date]) In (6,7), 0, 1) As IsBusinessDay  
From tbl
)
Delete From tbl
Where [Date] Not In (Select Top(@n) [Date] From CTE Order By IsBusinessDay Desc, [Date] Desc)

如果每天只有一个日期,你可以简单地这样做:

SELECT TOP 7 [Date] FROM Table1 
WHERE 
  [Date] < GETDATE() AND DATENAME(weekday, [DATE]) NOT IN ('Saturday', 'Sunday')
ORDER BY
  [DATE] DESC

您可以得到从今天开始的第 7 个工作日作为

  select top(1) cast(dateadd(d, -n + 1, getdate()) as date) d
  from (
    select  n
       , sum (case when datename(dw, dateadd(d, -n + 1, getdate())) not in ('Sunday',  'Saturday') then 1 end) over(order by n) wdn
    from (
       values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11)
    )t0(n)
  ) t
  where wdn = 7
  order by n;

通常在第@n 天使用即时计数

declare @n int = 24;

with t0(n) as (
  select n 
  from (
    values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
  ) t(n)
), tally as (
     select top(@n + (@n/5 +1)*2) row_number() over(order by t1.n)  n
     from t0 t1, t0 t2, t0 t3
)
select top(1) cast(dateadd(d, -n + 1, getdate()) as date) d
from (
  select  n
     , sum (case when datename(dw, dateadd(d, -n + 1, getdate())) not in ('Sunday',  'Saturday') then 1 end) over(order by n) wdn
  from  tally
) t
where wdn = @n
order by n;