这就是Dates
表派上用场的地方。有许多博客文章建议将一个Dates
表添加到数据库中,用于需要处理日期的情况。
为了创建一个Dates
表,你可以使用递归CTE:
;with dates as (
select cast('19000101' as datetime) [current_date]
union all
select dateadd(day, 1, current_date)
from dates
where current_date <= cast('20991231' as datetime)
)
select
[current_date]
, NULL [holiday]
, case datename(weekday, prev_date)
when 'Saturday'
then 1
when 'Sunday'
then 1
else 0
end [weekend]
into Dates
from dates
option(maxrecursion 0);
正如你可以看到我添加的,这可能是在未来有帮助的两个额外列。如果某个特定的日子是节假日/国家休息日,则可以包含布尔值以指向 - [holiday]
列。
如果一天是周末的一天,第三栏还包含布尔值。
因此,使用Dates
表,在一个单一的查询,你可以做这样的事情(这是不漂亮):
-- I'll also create the sample data and store it into a timeOff table
create table timeOff (staffCode varchar(25), holidayDate datetime);
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-03T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-04T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-05T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-06T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-07T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-10T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-11T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-12T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-13T00:00:00.000' AS DateTime));
insert [dbo].[timeOff] ([staffCode], [holidayDate]) values (N'J.Smith', CAST(N'2017-04-18T00:00:00.000' AS DateTime));
-- And now for the query itself (it's not pretty but I came up with it in a short time)
select
[staffCode]
, min([current_date]) [firstDay]
, max([current_date]) [lastDay]
from
(select d.[current_date]
, t.staffCode
, min(case when d.weekend = 0 and t.holidayDate is null then d.[current_date] else null end) over() [last_date]
from
(select [staffCode]
, min(holidayDate) [mindate]
, max(holidayDate) [maxdate]
from timeOff t
where staffcode = 'J.Smith'
group by staffCode) r
inner join dates d on d.[current_date] between mindate and maxdate
left join timeOff t on d.[current_date] = t.holidayDate) r
where [current_date] < [last_date]
and staffCode is not null
group by staffCode;
FYI:你会得到更多的答案(更公开程度),如果你需要包含通用标签(在这种情况下是sql server),然后是 – TheGameiswar
,你的意思是说除了周末以外的连续日期的说明和最大日期。不是吗?那么为什么2017-04-18是昨天,因为它不会连续下跌。最后一天应该是2017-04-13 – KumarHarsh
对不起@kumarharsh我使用的例子中有一个银行假期,所以周一不是工作日。但我可以忽略这些。谢谢。 – GPH