我有一个在工作日(周一至周五)运行的ssis包。如果我在星期二,背景(DB)收到文件,它需要上一个工作日日期并进行一些交易。如果我在星期五运行这份工作,它必须获取星期一的日期并处理交易。
我使用以下查询来获取上一个营业日期
Select Convert(varchar(50), Position_ID) as Position_ID,
TransAmount_Base,
Insert_Date as InsertDate
from tblsample
Where AsOfdate = Dateadd(dd, -1, Convert(datetime, Convert(varchar(10), '03/28/2012', 101), 120))
Order By Position_ID
如果我执行此查询,我将获得昨天Transactios的结果。如果我在星期一运行相同的查询,它必须获取星期五的交易而不是星期日。
答案 0 :(得分:45)
SELECT DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()))
我更喜欢在DATENAME
上使用DATEPART
这样的内容,因为它不需要设置DATEFIRST
并确保本地计算机上时间/日期设置的变化不会影响结果。最后DATEDIFF(DAY, 0, GETDATE())
将删除GETDATE()
的时间部分,无需转换为varchar(慢得多)。
编辑(差不多2年)
这个答案在我职业生涯的早期就已经很早了,每次上调都会让我感到懊恼,因为我不再同意使用DATENAME的情绪。
更多的解决方案是:
SELECT DATEADD(DAY, CASE (DATEPART(WEEKDAY, GETDATE()) + @@DATEFIRST) % 7
WHEN 1 THEN -2
WHEN 2 THEN -3
ELSE -1
END, DATEDIFF(DAY, 0, GETDATE()));
这适用于所有语言和DATEFIRST设置。
答案 1 :(得分:3)
那怎么样:
declare @dt datetime='1 dec 2012'
select case when 8-@@DATEFIRST=DATEPART(dw,@dt)
then DATEADD(d,-2,@dt)
when (9-@@DATEFIRST)%7=DATEPART(dw,@dt)%7
then DATEADD(d,-3,@dt)
else DATEADD(d,-1,@dt)
end
答案 2 :(得分:1)
查找上一个工作日的最简单方法是使用calendar table,其中包含名为IsBusinessDay
的列或类似内容。您的查询是这样的:
select max(BaseDate)
from dbo.Calendar c
where c.IsBusinessDay = 0x1 and c.BaseDate < @InputDate
使用函数的问题在于,当(因为)您必须因任何原因(国家法定假日等)创建异常时,代码很快就会变得不可维护;使用该表,您只需UPDATE
一个值。表格还可以更轻松地回答诸如“日期X和Y之间有多少个工作日”之类的问题,这在报告任务中非常常见。
答案 3 :(得分:1)
您可以轻松地将其作为函数调用,添加第二个参数以将GetDate()替换为您想要的任何日期。 如果您更改GetDate(),它将适用于任何日期范围内的任何一天。 如果星期几是输入日期(GetDate())
,则不会更改日期Declare @DayOfWeek As Integer = 2 -- Monday
Select DateAdd(Day, ((DatePart(dw,GetDate()) + (7 - @DayOfWeek)) * -1) % 7, Convert(Date,GetDate()))
答案 4 :(得分:1)
此函数返回上一个工作日,并考虑到假期和周末。您将需要创建一个简单的假期表。
-- =============================================
-- Author: Dale Kilian
-- Create date: 2019-04-29
-- Description: recursive function returns last work day for weekends and
-- holidays
-- =============================================
ALTER FUNCTION dbo.fnGetWorkWeekday
(
@theDate DATE
)
RETURNS DATE
AS
BEGIN
DECLARE @importDate DATE = @theDate
DECLARE @returnDate DATE
--Holidays
IF EXISTS(SELECT 1 FROM dbo.Holidays WHERE isDeleted = 0 AND @theDate = Holiday_Date)
BEGIN
SET @importDate = DATEADD(DAY,-1,@theDate);
SET @importDate = (SELECT dbo.fnGetWorkWeekday(@importDate))
END
--Satruday
IF(DATEPART(WEEKDAY,@theDate) = 7)
BEGIN
SET @importDate = DATEADD(DAY,-1,@theDate);
SET @importDate = (SELECT dbo.fnGetWorkWeekday(@importDate))
END
--Sunday
IF(DATEPART(WEEKDAY,@theDate) = 1)
BEGIN
SET @importDate = DATEADD(DAY,-2,@theDate);
SET @importDate = (SELECT dbo.fnGetWorkWeekday(@importDate))
END
RETURN @importDate;
END
GO
答案 5 :(得分:0)
select
dateadd(dd,
case DATEPART(dw, getdate())
when 1
then -2
when 2
then -3
else -1
end, GETDATE())
答案 6 :(得分:0)
感谢上面的提示,我对查询略有不同,因为我的用户需要上一个营业日期的所有值。例如,今天是星期一,所以他需要在上周五午夜到周六午夜之间的所有事情。我使用上面的组合和“之间”这样做,只要有人感兴趣。我不是一个庞大的技术人员。
-- Declare a variable for the start and end dates.
declare @StartDate as datetime
declare @EndDate as datetime
SELECT @StartDate = DATEADD(DAY, CASE DATENAME(WEEKDAY, GETDATE())
WHEN 'Sunday' THEN -2
WHEN 'Monday' THEN -3
ELSE -1 END, DATEDIFF(DAY, 0, GETDATE()))
select @EndDate = @StartDate + 1
select @StartDate , @EndDate
-- Later on in the query use "between"
and mydate between @StartDate and @EndDate
答案 7 :(得分:0)
更优雅:
select DATEADD(DAY,
CASE when datepart (dw,Getdate()) < 3 then datepart (dw,Getdate()) * -1 + -1 ELSE -1 END,
cast(GETDATE() as date))