因此,我希望在开始日期和结束日期之间确定这两个日期之间出现的特定日期。
那么星期一,星期二等等。
我知道我可以在开始日期和结束日期之间循环并检查每一天,但差异可能是很多天。我更喜欢不需要循环的东西。有任何想法吗? (必须在SQL Server 2005 +中支持)
答案 0 :(得分:8)
考虑到我想要的想法,我们应该这样做:
SET DATEFIRST 1
DECLARE
@start_date DATETIME,
@end_date DATETIME
SET @start_date = '2011-07-11'
SET @end_date = '2011-07-22'
;WITH Days_Of_The_Week AS (
SELECT 1 AS day_number, 'Monday' AS day_name UNION ALL
SELECT 2 AS day_number, 'Tuesday' AS day_name UNION ALL
SELECT 3 AS day_number, 'Wednesday' AS day_name UNION ALL
SELECT 4 AS day_number, 'Thursday' AS day_name UNION ALL
SELECT 5 AS day_number, 'Friday' AS day_name UNION ALL
SELECT 6 AS day_number, 'Saturday' AS day_name UNION ALL
SELECT 7 AS day_number, 'Sunday' AS day_name
)
SELECT
day_name,
1 + DATEDIFF(wk, @start_date, @end_date) -
CASE WHEN DATEPART(weekday, @start_date) > day_number THEN 1 ELSE 0 END -
CASE WHEN DATEPART(weekday, @end_date) < day_number THEN 1 ELSE 0 END
FROM
Days_Of_The_Week
答案 1 :(得分:6)
我不确定OP之后是什么,这将每周计算一次:
SET DATEFIRST 1
DECLARE @StartDate datetime
,@EndDate datetime
SELECT @StartDate='7/13/2011'
,@EndDate='7/28/2011'
;with AllDates AS
(
SELECT @StartDate AS DateOf, datename(weekday,@StartDate) AS WeekDayName, datepart(weekday,@StartDate) AS WeekDayNumber
UNION ALL
SELECT DateOf+1, datename(weekday,DateOf+1), datepart(weekday,DateOf+1)
FROM AllDates
WHERE DateOf<@EndDate
)
SELECT COUNT(*) CountOf,WeekDayName FROM AllDates GROUP BY WeekDayName,WeekDayNumber ORDER BY WeekDayNumber
输出:
CountOf WeekDayName
----------- ------------------------------
2 Monday
2 Tuesday
3 Wednesday
3 Thursday
2 Friday
2 Saturday
2 Sunday
(7 row(s) affected)
这将计算周一至周五的日期:
SET DATEFIRST 1
DECLARE @StartDate datetime
,@EndDate datetime
SELECT @StartDate='7/13/2011'
,@EndDate='7/28/2011'
;with AllDates AS
(
SELECT @StartDate AS DateOf, datepart(weekday,@StartDate) AS WeekDayNumber
UNION ALL
SELECT DateOf+1, datepart(weekday,DateOf+1)
FROM AllDates
WHERE DateOf<@EndDate
)
SELECT COUNT(*) AS WeekDayCount FROM AllDates WHERE WeekDayNumber<=5
输出:
WeekDayCount
------------
12
(1 row(s) affected)
如果您有假期表,您可以加入并删除它们。这是一个稍微不同的版本,可以更好地执行:
SET DATEFIRST 1
DECLARE @StartDate datetime
,@EndDate datetime
SELECT @StartDate='7/13/2011'
,@EndDate='7/28/2011'
;with AllDates AS
(
SELECT @StartDate AS DateOf, datepart(weekday,getdate()) AS WeekDayNumber
UNION ALL
SELECT DateOf+1, (WeekDayNumber+1) % 7
FROM AllDates
WHERE DateOf<@EndDate
)
SELECT COUNT(*) AS WeekDayCount FROM AllDates WHERE WeekDayNumber>0 AND WeekDayNumber<6
--I don't like using "BETWEEN", ">", ">=", "<", and "<=" are more explicit in defining end points
产生与原始查询相同的输出。
答案 2 :(得分:2)
这假设standard settings但可以改编
DECLARE @StartDate datetime, @EndDate datetime
SELECT @StartDate='20110601', @EndDate='20110630'
;WITH AllDates AS
(
SELECT @StartDate AS DateOf, datepart(weekday, @StartDate) AS WeekDayNumber
UNION ALL
SELECT DateOf+1, datepart(weekday, DateOf+1)
FROM AllDates
WHERE DateOf < @EndDate
)
SELECT SUM(CASE WHEN WeekDayNumber BETWEEN 2 AND 6 THEN 1 ELSE 0 END) AS WeekDayCount
FROM AllDates
OPTION (MAXRECURSION 0)
答案 3 :(得分:1)
这应该对SQL Server有效,并且应该是国际化安全的(注意:我不有一个服务器来测试它)。
SELECT datediff(day, @start, @end) - datediff(week, @start, @end) * 2
- CASE WHEN datepart(weekday, @start)
IN (datepart(weekday, '1970-01-03'),
datepart(weekday, '1970-01-04'))
THEN 1
ELSE 0 END,
- CASE WHEN datepart(weekday, @end)
IN (datepart(weekday, '1970-01-03'),
datepart(weekday, '1970-01-04'))
THEN 1
ELSE 0 END
给那个旋转。
鉴于澄清,这应该得到每天的数量 不使用递归,应该完全是国际安全的。您必须根据需要调整包含/排除的开始/结束日期参数(我使用的DB2版本检查此项排除了开始日期,但包括结束日期,例如)。
WITH dayOfWeek (name, dayNumber) as (VALUES(dayname(weekday, '1970-01-01'), daypart(weekday, '1970-01-01')),
(dayname(weekday, '1970-01-02'), daypart(weekday, '1970-01-02')),
(dayname(weekday, '1970-01-03'), daypart(weekday, '1970-01-03')),
(dayname(weekday, '1970-01-04'), daypart(weekday, '1970-01-04')),
(dayname(weekday, '1970-01-05'), daypart(weekday, '1970-01-05')),
(dayname(weekday, '1970-01-06'), daypart(weekday, '1970-01-06')),
(dayname(weekday, '1970-01-07'), daypart(weekday, '1970-01-07')))
SELECT name, dayNumber, datediff(weeks, @start, @end)
+ CASE WHEN datepart(weekday, @end) >= dayNumber THEN 1 ELSE 0 END
- CASE WHEN datepart(weekday, @start) >= dayNumber THEN 1 ELSE 0 END
FROM dayOfWeek
这对你有帮助吗?
答案 4 :(得分:0)
答案 5 :(得分:0)
我会简单地在标记的答案中添加评论,但没有足够的“声誉”。您可以通过发现一周中每一天的工作日来设置它,而不是硬编码依赖于datefirst的day_number:
;WITH Days_Of_The_Week AS (
SELECT DATEPART(dw, '2007-01-01') AS day_number, 'Monday' AS day_name UNION ALL -- 2007-01-01 is a known Monday
SELECT DATEPART(dw, '2007-01-02') AS day_number, 'Tuesday' AS day_name UNION ALL
SELECT DATEPART(dw, '2007-01-03') AS day_number, 'Wednesday' AS day_name UNION ALL
SELECT DATEPART(dw, '2007-01-04') AS day_number, 'Thursday' AS day_name UNION ALL
SELECT DATEPART(dw, '2007-01-05') AS day_number, 'Friday' AS day_name UNION ALL
SELECT DATEPART(dw, '2007-01-06') AS day_number, 'Saturday' AS day_name UNION ALL
SELECT DATEPART(dw, '2007-01-07') AS day_number, 'Sunday' AS day_name
)
答案 6 :(得分:0)
@start_date date = '2017-08-11',
@end_date date = '2017-08-27',
@weekday int = 7,
@count int output
As
Begin
Declare @i int = 0
set @count = 0
while(@i <= (select Datediff(Day, @start_date, @end_date)))
begin
if(Dateadd(Day, @i, @start_date) > @end_date)
break
if(Datepart(weekday, Dateadd(Day, @i, @start_date)) = @weekday)
set @count += 1
set @i += 1
end
select @count