我想计算给定日期范围(开放日和结束日)之间的营业时间
例如:营业时间
ID WeekName OpeningHour ClosingHour
01 Monday 8.00AM 4.00PM
02 Tuesday 8.00AM 4.00PM
03 Wednesday 8.00AM 4.00PM
04 Thursday 8.00AM 4.00PM
05 Friday 8.00AM 4.00PM
如果我给出例如日期范围
开放日:01/04/2014 09.00AM
闭幕日:03/04/2014 14.00 AM
我想从给定的日期范围计算营业时间 给定范围之间有3天
01/04/2014
02/04/2014
03/04/2014
首先,我想查看日期名称并计算营业时间(从上表开始)的小时数。
01/04/2014 - 星期二
02/04/2014 - 周三
03/04/2014 - 周四
我期待的结果:
GivenDate DayID DayName DateDiff
01/04/2014 01 Tuesday 7
02/04/2014 02 Wednesday 8
03/04/2014 03 Thursday 6
答案 0 :(得分:1)
在Stackoverflow上,通常不赞成问一个问题,期待别人为你做你的工作。您至少应该显示一些最小的努力,例如到目前为止您尝试过的一些SQL。
那就是说,这里的查询会返回你想要的内容。即使您没有日期(日历)表,此查询仍然有效,因为它会从系统表生成一系列数字。然后,这些数字又被添加到开始日期,以便在该区间内每天返回一条记录:
SELECT * INTO #WorkingHours
FROM (VALUES (1, 'Monday', '08:00', '16:00')
,(2, 'Tuesday', '08:00', '16:00')
,(3, 'Wednesday', '08:00', '16:00')
,(4, 'Thursday', '08:00', '16:00')
,(5, 'Friday', '08:00', '16:00'))
E(DayId, DayName, OpeningHour, ClosingHour)
DECLARE @StartDate DATETIME = '2014-04-01 09:00:00'
DECLARE @EndDate DATETIME = '2014-04-03 14:00:00'
SELECT [GivenDate], [DayID], [DayName],
DATEDIFF(HOUR, CASE WHEN @StartDate > [OpeningDateTime] THEN @StartDate ELSE [OpeningDateTime] END,
CASE WHEN @EndDate < [ClosingDateTime] THEN @EndDate ELSE [ClosingDateTime] END) AS [DateDiff]
FROM (
SELECT CAST(@StartDate + n - 1 AS DATE) AS [GivenDate]
, n AS [DayID]
, DATENAME(dw, @StartDate + n - 1) AS [DayName]
, CAST(CAST(CAST(@StartDate + n - 1 AS DATE) AS VARCHAR) + ' ' + OpeningHour AS DateTime) AS OpeningDateTime
, CAST(CAST(CAST(@StartDate + n - 1 AS DATE) AS VARCHAR) + ' ' + ClosingHour AS DateTime) AS ClosingDateTime
FROM
-- Numbers, for expanding the date range:
(SELECT ROW_NUMBER() OVER (ORDER BY object_id) n FROM sys.all_objects) Numbers
INNER JOIN #WorkingHours ON DayName = DATENAME(dw, @StartDate + n - 1)
WHERE Numbers.n <= DATEDIFF(d, @StartDate, @EndDate) + 1
) SubQuery
以下是结果输出:
答案 1 :(得分:0)
如果您有日期(日历)表,这非常简单。首先,您将开始日期和结束日期加入日历表以获取日期。比你只需将DATENAME
与你桌上的内容进行比较。下面是使用表变量和DATE
(日历)表的示例代码。
DECLARE @BusHours TABLE
(
ID INT
,DayOfWeekName VARCHAR(10)
,OpeningHour VARCHAR(7)
,ClosingHOur VARCHAR(7)
)
INSERT INTO @BusHours
( ID, DayOfWeekName, OpeningHour, ClosingHour )
VALUES ( 1, 'Monday', '08:00AM', '04:00PM' )
, ( 2, 'Tuesday', '08:00AM', '04:00PM' )
, ( 3, 'Wednesday', '08:00AM', '04:00PM' )
, ( 4, 'Thursday', '08:00AM', '04:00PM' )
, ( 5, 'Friday', '08:00AM', '04:00PM' )
DECLARE @StartDate DATETIME = '04/01/2014 09:00AM'
,@EndDate DATETIME = '04/03/2014 14:00PM'
SELECT d.Date_Dt AS GivenDate
,b.ID AS DayID
,b.DayOfWeekName AS DayName
,CASE WHEN DATENAME(WEEKDAY, @StartDate) = b.DayOfWeekName
THEN DATEDIFF(hh, @StartDate,
CONVERT(DATETIME, CONVERT(VARCHAR(12), @StartDate, 101) + ' ' + b.ClosingHour))
WHEN DATENAME(WEEKDAY, @EndDate) = b.DayOfWeekName
THEN DATEDIFF(hh, CONVERT(DATETIME, CONVERT(VARCHAR(12), @EndDate, 101) + ' ' + b.OpeningHour), @EndDate)
ELSE DATEDIFF(hh, CONVERT(DATETIME, '01/01/2014' + ' ' + b.OpeningHour),
CONVERT(DATETIME, '01/01/2014' + ' ' + b.ClosingHour))
END AS HoursOperation
FROM dbo.Date AS d
JOIN @BusHours AS b
ON DATENAME(WEEKDAY, d.Date_Dt) = b.DayOfWeekName
WHERE d.Date_Dt >= CONVERT(DATE, @startDate)
AND d.Date_Dt <= CONVERT(DATE, @EndDate)
我工作中[Date]
表的表定义。不是每个人都有相同的实现,但如果你四处搜索,你可以找到许多脚本来生成它。
CREATE TABLE [dbo].[Date]
(
[Date_Id] [int] NOT NULL
,[Date_Dt] [date] NULL
,[Date_Nm] [varchar](9) NULL
,[DayType_Cd] [varchar](7) NULL
,[DayofWeek_Nbr] [int] NULL
,[DayofWeek_Nm] [varchar](10) NULL
,[DayofMonth_Nbr] [int] NULL
,[DayofYear_Nbr] [int] NULL
,[Week_Nbr] [int] NULL
,[Week_Nm] [varchar](5) NULL
,[WeekFirstDay_Dt] [date] NULL
,[WeekLastDay_Dt] [date] NULL
,[WeekofYear_Nbr] [int] NULL
,[Month_Nbr] [int] NULL
,[Month_6_Nbr] [int] NULL
,[Month_Nm] [varchar](6) NULL
,[MonthFull_Nm] [varchar](9) NULL
,[MonthLastDay_Dt] [date] NULL
,[MonthofYear_Nbr] [int] NULL
,[Quarter_Nbr] [int] NULL
,[Quarter_Nm] [varchar](5) NULL
,[QuarterofYear_Nbr] [int] NULL
,[Year_Nbr] [int] NULL
,[Year_Nm] [varchar](4) NULL
,[FYDayofWeek_Nbr] [int] NULL
,[FYWeek_Nbr] [int] NULL
,[FYWeek_Nm] [varchar](5) NULL
,[FYWeekFirstDay_Dt] [date] NULL
,[FYWeekLastDay_Dt] [date] NULL
,[FYWeekofYear_Nbr] [int] NULL
)