我想构建一个SQL查询,计算两个日期之间的差异,但在结果中不计周末天数。
有没有办法格式化日期以获得此结果?例如针对Oracle数据库:
select sysdate - creation_dttm from the_table
CREATE FUNCTION TOTAL_WEEKDAYS(date1 DATE, date2 DATE)
RETURNS INT
RETURN ABS(DATEDIFF(date2, date1)) + 1
- ABS(DATEDIFF(ADDDATE(date2, INTERVAL 1 - DAYOFWEEK(date2) DAY),
ADDDATE(date1, INTERVAL 1 - DAYOFWEEK(date1) DAY))) / 7 * 2
- (DAYOFWEEK(IF(date1 < date2, date1, date2)) = 1)
- (DAYOFWEEK(IF(date1 > date2, date1, date2)) = 7);
测试:
SELECT TOTAL_WEEKDAYS('2013-08-03', '2013-08-21') weekdays1,
TOTAL_WEEKDAYS('2013-08-21', '2013-08-03') weekdays2;
结果:
| WEEKDAYS1 | WEEKDAYS2 |
-------------------------
| 13 | 13 |
我发现了另一种只使用SQL来计算差异的方法:
select sysdate - creation_dttm
- 2 * (to_char(sysdate, 'WW') - to_char(creation_dttm, 'WW'))
from the_table
我发现这个帖子中的一些答案并没有达到它们所声称的效果。经过一些实验、测试和调整,我有以下贡献。
declare @firstdate Date
declare @seconddate Date
set @firstDate = convert(date, '2016-03-07')
set @seconddate = convert(date, '2016-04-04')
select (datediff(dd, @firstDate, @secondDate)) -
(( DateDiff(wk, @firstDate, @secondDate) * 2) -
case when datepart(dw, @FirstDate) = 7 then 1 else 0 end -
case when datepart(dw, @secondDate) = 7 then -1 else 0 end)
包含测试工具 - 你只需要调整两个日期并运行自己的测试。这假设相邻两个工作日之间的差距为1。如果您所在的国家使用不同的日期来表示周末,则必须相应地设置日期基准,以便您的“星期六”为7,而您的“星期日”为1。
来自之前的帖子:
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @StartDate = '2008/10/01'
SET @EndDate = '2008/10/31'
SELECT
(DATEDIFF(dd, @StartDate, @EndDate) + 1)
-(DATEDIFF(wk, @StartDate, @EndDate) * 2)
-(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END)
SELECT
&&START_DATE_YYYYMMDD "Start Date", --in YYYYMMDD format
&&END_DATE_YYYYMMDD "End Date", --in YYYYMMDD format
&&WK_WORK_DAY_CNT "Week Work Day Count", --Number of work day per week
&&DATE_SEQ_NORML_FACTOR "Normalization Factor", --set to 1 when run in Oracle
CASE
WHEN
FLOOR( TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR / 7 ) =
FLOOR( TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR / 7 )
THEN(
TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) -
TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + 1
)
ELSE(
(
&&WK_WORK_DAY_CNT - MOD( TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR , 7 ) + 1
) +
MOD( TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR , 7 ) +
(
(
(
TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) -
MOD( TO_CHAR( TO_DATE( &&END_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR , 7 )
) -
(
TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) +
(
7 -
(
MOD( TO_CHAR( TO_DATE( &&START_DATE_YYYYMMDD , 'YYYYMMDD') , 'J' ) + &&DATE_SEQ_NORML_FACTOR , 7 )
)
)
)
) / 7 * &&WK_WORK_DAY_CNT
)
) END "Week Day Count"
FROM DUAL
((sysdate - ced.created_dt) + ((((to_char(ced.created_dt,'IW') - ((to_char(sysdate,'YY') - to_char(ced.created_dt,'YY'))* 52))
- to_char(to_char(sysdate,'IW')))) * 2)) duration_in_weekdays
DECLARE @range INT;
SET @range = DATEDIFF(DAY, @FirstDate, @SecondDate);
SET @NumWorkDays = (
SELECT
@range / 7 * 5 + @range % 7 - (
SELECT COUNT(*)
FROM (
SELECT 1 AS d
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
) weekdays
WHERE d <= @range % 7
AND DATENAME(WEEKDAY, @SecondDate - d) IN ('Saturday', 'Sunday'))
);
我已经更新了@JOpuckman的函数,以考虑到不同地区并非总是有周六和周日的周末。如果其他人需要在全球范围内应用此功能,请参考以下代码;
DECLARE @FirstDate DateTime
DECLARE @SecondDate DateTime
SET @FirstDate = '08-20-2012'
SET @SecondDate = '08-24-2012'
DECLARE @range INT;
DECLARE @WeekendDayNameStart VARCHAR(50)
DECLARE @WeekendDayNameEnd VARCHAR(50)
SET @WeekendDayNameStart = 'FRIDAY'
SET @WeekendDayNameEnd = (
SELECT CASE @WeekendDayNameStart
WHEN 'SUNDAY' THEN 'MONDAY'
WHEN 'MONDAY' THEN 'TUESDAY'
WHEN 'TUESDAY' THEN 'WEDNESDAY'
WHEN 'WEDNESDAY' THEN 'THURSDAY'
WHEN 'THURSDAY' THEN 'FRIDAY'
WHEN 'FRIDAY' THEN 'SATURDAY'
WHEN 'SATURDAY' THEN 'SUNDAY'
END
)
DECLARE @NumWorkDays INT
SET @range = DATEDIFF(DAY, @FirstDate, @SecondDate);
SET @NumWorkDays = (
SELECT
@range / 7 * 5 + @range % 7 - (
SELECT COUNT(*)
FROM (
SELECT 1 AS d
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
) weekdays
WHERE d <= @range % 7
AND DATENAME(WEEKDAY, @SecondDate - d) IN (@WeekendDayNameStart, @WeekendDayNameEnd))
);
-- Calculate whether the current date is a working day
DECLARE @CurDateExtra INT
SET @CurDateExtra =
(
CASE DATENAME(WEEKDAY, @SecondDate)
WHEN @WeekendDayNameStart THEN 0
WHEN @WeekendDayNameEnd THEN 0
ELSE 1
END
)
SET @NumWorkDays = @NumWorkDays + @CurDateExtra
SELECT @NumWorkDays
SELECT
Id,
DATEDIFF(d, datefrom, dateto) AS TotDays,
DATEDIFF(wk, datefrom, dateto) AS Wkds,
DATEDIFF(d, datefrom, dateto) - DATEDIFF(wk, datefrom, dateto) AS Days
FROM
YOURTABLE
sysdate
和creation_dttm
都不返回周末日期时,它很可能会起作用。 - Andriy M