用户将选择前端和灵活日期的日期,例如,如果他们选择'2014-07-17'作为日期,灵活日期为2,那么我们需要显示前2个和下2个工作日,如下所示,
不包括周末(周五和周六),周末是星期五和星期六。
我使用了以下查询
DECLARE @MinDate DATE, @MaxDate DATE;
SELECT @MinDate = DATEADD(Day, -@inyDays ,@dtDate), @MaxDate = DATEADD(Day,@inyDays ,@dtDate)
DECLARE @DayExclusionValue VARCHAR(20)
SELECT @DayExclusionValue = dbo.UDF_GetConfigSettingValue('DaysToExclude')
DECLARE @NumOfWeekends INT
SELECT @NumOfWeekends= (DATEDIFF(wk, @MinDate, @MaxDate) * 2) +(CASE WHEN DATENAME(dw, @MinDate) = 'Friday' THEN 1 ELSE 0 END) +(CASE WHEN DATENAME(dw, @MaxDate) = 'Saturday' THEN 1 ELSE 0 END)
SET @MaxDate = DATEADD(Day,@inyDays + @NumOfWeekends ,@dtDate)
;WITH CalculatedDates AS
(
SELECT dates = @MinDate
UNION ALL
SELECT DATEADD(day, 1, dates)
FROM CalculatedDates
WHERE DATEADD(day, 1, dates) <= @MaxDate
)
SELECT dates FROM CalculatedDates
WHERE dates >= CAST(GETDATE() AS DATE)
AND DATENAME(DW, dates) NOT IN (SELECT Value FROM UDF_GetTableFromString(@DayExclusionValue))
OPTION (MAXRECURSION 0);
但上述查询无效。
你能不能给我建议任何其他解决方案。
答案 0 :(得分:0)
此示例适用于Oracle,您没有说明您使用的是什么数据库。如果您有假期列表,您需要按照指示加入。它需要是一个外连接,你需要添加一个案例或某些东西,以便度假表排除&#39;天覆盖生成的天数。
我也随机选择了乘数。当只处理周末8时绰绰有余,但如果你的假期表包括很多连续的休假日,它可能不再是。
select d from(
select rownum nn, d, sysdate - d, first_value (rownum) over (order by abs(sysdate-d)) zero_valu
from (
select sysdate+n d, to_char(sysdate+n,'DAY'), CASE to_char(sysdate+n,'D') WHEN '6' THEN 'exclude' WHEN '7' THEN 'exclude' ELSE 'include' END e_or_i from
(SELECT ROWNUM-9 n -- 9=flexibleday*8/2 +1
FROM ( SELECT 1 just_a_column
FROM dual
CONNECT BY LEVEL <= 16 -- 8=flexibleday * 8
)
)
) where e_or_i = 'include' -- in this step you need to join in a table of holidays or such if you need that.
) where abs(nn-7) <= 2 -- 2=flexiday
order by d
答案 1 :(得分:0)
DECLARE @StartDate DATE = '2014-07-17';
SELECT *
FROM
(
--Show Closest Previous 2 Days Not In Friday or Saturday
SELECT TOP 2
DATEADD(DAY, -nr, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, -nr, @StartDate)) CheckName,
-nr CheckCount
FROM (VALUES(1),(2),(3),(4)) AS Numbers(nr)
WHERE DATENAME(DW, DATEADD(DAY, -nr, @StartDate)) NOT IN ('Friday','Saturday')
UNION ALL
--Show Todays Date If Not Friday or Saturday
SELECT TOP 1
DATEADD(DAY, +nr, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, +nr, @StartDate)) CheckName,
nr CheckCount
FROM (VALUES(0)) AS Numbers(nr)
WHERE DATENAME(DW, DATEADD(DAY, +nr, @StartDate)) NOT IN ('Friday','Saturday')
UNION ALL
--Show Closest Next 2 Days Not In Friday or Saturday
SELECT TOP 2
DATEADD(DAY, +nr, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, +nr, @StartDate)) CheckName,
nr CheckCount
FROM (VALUES(1),(2),(3),(4)) AS Numbers(nr)
WHERE DATENAME(DW, DATEADD(DAY, +nr, @StartDate)) NOT IN ('Friday','Saturday')
) d
ORDER BY d.CheckDate
我将其分为3个部分,前2天,今天(如果适用)和接下来的2天 这是输出:
CheckDate CheckName CheckCount
2014-07-15 Tuesday -2
2014-07-16 Wednesday -1
2014-07-17 Thursday 0
2014-07-20 Sunday 3
2014-07-21 Monday 4
我使用日期名称,因为不确定服务器设置为@@ datefirst的是什么。 values()部分只是一个数字表(您应该创建一个数字表,与您想要返回的记录数量以及您要越过的任何周末一样大)然后将替换第一部分和最后部分中的TOP 2以及您希望在之前和之后返回的天数。
****添加了通用数字表功能的更新:
我们在此声明我们想要提取的开始日期和上一天和下一天的数量:
DECLARE @StartDate DATE = '2014-07-20';
DECLARE @MaxBusDays INT = 5
下一节创建一个数字表(可以通过谷歌轻松找到)
DECLARE @number_of_numbers INT = 100000;
;WITH
a AS (SELECT 1 AS i UNION ALL SELECT 1),
b AS (SELECT 1 AS i FROM a AS x, a AS y),
c AS (SELECT 1 AS i FROM b AS x, b AS y),
d AS (SELECT 1 AS i FROM c AS x, c AS y),
e AS (SELECT 1 AS i FROM d AS x, d AS y),
f AS (SELECT 1 AS i FROM e AS x, e AS y),
numbers AS
(
SELECT TOP(@number_of_numbers)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS number
FROM f
)
现在我们使用数字表和row_number设置来仅提取工作日之前和之后的行数(加上所需的日期,如果它不是fri / sat)(不是fri / sat)
SELECT *
FROM
(
--Show Closest Previous x Working Days (Not Friday or Saturday)
SELECT * FROM
(
SELECT
DATEADD(DAY, -number, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, -number, @StartDate)) CheckName,
-number CheckCount,
ROW_NUMBER() OVER (ORDER BY number ASC) AS RowCounter
FROM Numbers
WHERE DATENAME(DW, DATEADD(DAY, -number, @StartDate)) NOT IN ('Friday','Saturday')
) a
WHERE a.RowCounter <= @MaxBusDays
UNION ALL
--Show Todays Date If Working Day (Not Friday or Saturday)
SELECT TOP 1
@StartDate CheckDate,
DATENAME(DW, @StartDate) CheckName,
0 CheckCount,
0 RowCounter
WHERE DATENAME(DW, @StartDate) NOT IN ('Friday','Saturday')
UNION ALL
--Show Closest Next x Working Days (Not Friday or Saturday)
SELECT * FROM
(
SELECT
DATEADD(DAY, +number, @StartDate) CheckDate,
DATENAME(DW, DATEADD(DAY, +number, @StartDate)) CheckName,
number CheckCount,
ROW_NUMBER() OVER (ORDER BY number ASC) AS RowCounter
FROM Numbers
WHERE DATENAME(DW, DATEADD(DAY, +number, @StartDate)) NOT IN ('Friday','Saturday')
) b
WHERE b.RowCounter <= @MaxBusDays
) c
ORDER BY c.CheckDate
以下是输出:(2014-07-20是中间行)
CheckDate CheckName CheckCount RowCounter
2014-07-13 Sunday -7 5
2014-07-14 Monday -6 4
2014-07-15 Tuesday -5 3
2014-07-16 Wednesday -4 2
2014-07-17 Thursday -3 1
2014-07-20 Sunday 0 0
2014-07-21 Monday 1 1
2014-07-22 Tuesday 2 2
2014-07-23 Wednesday 3 3
2014-07-24 Thursday 4 4
2014-07-27 Sunday 7 5