SQL 工作日函数
SQL working days function
我正在尝试计算前 5 个工作日,如果是周六或周日,则需要使用周五作为最后一个工作日。
我得到了这个查询的 if else 部分,但是当我尝试使用它来创建一个函数时,我收到了错误消息,我错过了什么想法?
create table holidays (
date date);
GO
create function dbo.WorkDays
(
@date datetime,
@days int
)
returns date
as
Begin
IF datename(dw,@date) = 'Saturday'
select dateadd(dd,-1,thedate)
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
Else If datename(dw,@date) = 'Sunday'
select dateadd(dd,-1,thedate)
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
Else
select thedate
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
End
drop table holidays
显示的错误是:
Select 包含在函数中的语句不能 return 数据到客户端。
您需要声明一个@return变量,并将每个select语句的输出赋值给它:
create function dbo.WorkDays
(
@date datetime,
@days int
)
returns date
as
Begin
DECLARE @return date
IF datename(dw,@date) = 'Saturday'
select @return = dateadd(dd,-1,thedate)
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
Else If datename(dw,@date) = 'Sunday'
select @return = dateadd(dd,-1,thedate)
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
Else
select @return= thedate
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
return @return
End
我想你的查询逻辑是正确的。
USE [DBName]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[fnGetWorkdays]
(
@f datetime=null,@t datetime=null
)
RETURNS int
AS
BEGIN
declare @retVal int=0
set @retVal=(
select count(DyName) as DayCnt
from CalenderInfo where
DteName between @f and @t and DyName not in('Friday')
and DteName not in
( select Fromdate from HolidayInfo where Fromdate between @f and @t )
)
return @retVal
END
Table 1: 日历信息
DayID int
DyName varchar(20)
DteName datetime
Table 2: 假日信息
HolidayDetailsID int
HolidayID int
HolydayName varchar(100)
Fromdate datetime
Todate datetime
IsPublic int
IsCalculated int
IsInactive int
我正在尝试计算前 5 个工作日,如果是周六或周日,则需要使用周五作为最后一个工作日。
我得到了这个查询的 if else 部分,但是当我尝试使用它来创建一个函数时,我收到了错误消息,我错过了什么想法?
create table holidays (
date date);
GO
create function dbo.WorkDays
(
@date datetime,
@days int
)
returns date
as
Begin
IF datename(dw,@date) = 'Saturday'
select dateadd(dd,-1,thedate)
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
Else If datename(dw,@date) = 'Sunday'
select dateadd(dd,-1,thedate)
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
Else
select thedate
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
End
drop table holidays
显示的错误是: Select 包含在函数中的语句不能 return 数据到客户端。
您需要声明一个@return变量,并将每个select语句的输出赋值给它:
create function dbo.WorkDays
(
@date datetime,
@days int
)
returns date
as
Begin
DECLARE @return date
IF datename(dw,@date) = 'Saturday'
select @return = dateadd(dd,-1,thedate)
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
Else If datename(dw,@date) = 'Sunday'
select @return = dateadd(dd,-1,thedate)
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
Else
select @return= thedate
from (
select thedate=dateadd(d,-v.day,cast(@date as date)),
rn=row_number() over (order by v.day),
weekday = datename(dw,dateadd(d,-v.day,cast(@date as date)))
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))v(day)
left join holidays h on h.date = dateadd(d,v.day,cast(@date as date))
where left(datename(dw,dateadd(d,-v.day,cast(@date as date))),1) <> 'S'
) x
where @days = rn
return @return
End
我想你的查询逻辑是正确的。
USE [DBName]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[fnGetWorkdays]
(
@f datetime=null,@t datetime=null
)
RETURNS int
AS
BEGIN
declare @retVal int=0
set @retVal=(
select count(DyName) as DayCnt
from CalenderInfo where
DteName between @f and @t and DyName not in('Friday')
and DteName not in
( select Fromdate from HolidayInfo where Fromdate between @f and @t )
)
return @retVal
END
Table 1: 日历信息
DayID int
DyName varchar(20)
DteName datetime
Table 2: 假日信息
HolidayDetailsID int
HolidayID int
HolydayName varchar(100)
Fromdate datetime
Todate datetime
IsPublic int
IsCalculated int
IsInactive int