DAYOFWEEK 里面 while
DAYOFWEEK inside while
过去一个小时我一直在研究这个,但似乎无法让它发挥作用。
我需要做的就是插入这些值,但我需要跳过包含星期六或星期日的插入。
Begin Tran
Declare @VaccID int = 26
Declare @Clinic int = 36
Declare @Enroll int = 30
Declare @SignUp int = 0
Declare @BlnAct int = 1
Declare @BlnDis int = 1
Declare @DateStartTime datetime = '2015-09-16 11:00:00.000'
Declare @DateEndTime datetime = '2015-09-16 14:00:00.000'
Declare @EndDate date = '2015-10-16'
Declare @Days int = DATEDIFF(dd, @DateStartTime, @EndDate)
Select @DateStartTime, @DateEndTime, @Days
Declare @i int = 0
Declare @WeekDay varchar = ''
WHILE @i <= @Days
IF(@WeekDay = 'Monday' OR
@WeekDay = 'Tuesday' OR
@WeekDay = 'Wednesday' OR
@WeekDay = 'Thursday' OR
@WeekDay = 'Friday')
Begin
INSERT INTO dbo.tblSessions
([intVaccID],
[intLocationID],
[dtDateTimeStart],
[dtDateTimeStop],
[intEnrollmentMax],
[intSignedUp],
[blnActive],
[blnDisplay])
Values (@VaccID,
@Clinic,
DATEADD(dd, @i, @DateStartTime),
DATEADD(dd, @i, @DateEndTime),
@Enroll,
@SignUp,
@BlnAct,
@BlnDis)
SELECT @VaccID as intVaccID,
@Clinic as intLocationID,
DATEADD(dd, @i, @DateStartTime) as dtDateTimeStart,
DATEADD(dd, @i, @DateEndTime) as dtDateTimeStop,
@Enroll as intEnrollmentMax,
@SignUp as intSignedUp,
@BlnAct as blnActive,
@BlnDis as blnDisplay
SET @i = @i + 1
SET @WeekDay = DAYOFWEEK(dw, DATEADD(dd, @i, @DateStartTime))
END
Rollback Tran
Commit Tran
它至少在一周的每一天都在填写,但现在似乎在查询中途停滞不前。我知道我错过了一些可笑的小东西,但我似乎无法找到它。我想这是我今天的白鲸。
为什么不使用 GOTO 关键字跳过星期六和星期日:
实际上您的查询应该以其他方式重构。但是对于上面的场景你可以使用这个。
WHILE @i< @days
BEGIN
LABEL :
SET @i = @i + 1
SET @WeekDay = DAYOFWEEK(dw, DATEADD(dd, @i, @DateStartTime))
IF(@WeekDay = 'SATURDAY' OR @WeekDay = 'SUNDAY')
GOTO LABEL
END
您应该将其作为基于集合的操作来执行,而不是使用循环。使用计数 table 时无需循环。看看这是否不会产生所需的输出。
Declare @VaccID int = 26
, @Clinic int = 36
, @Enroll int = 30
, @SignUp int = 0
, @BlnAct int = 1
, @BlnDis int = 1
, @DateStartTime datetime = '2015-09-16 11:00:00.000'
, @DateEndTime datetime = '2015-09-16 14:00:00.000'
, @EndDate date = '2015-10-16';
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM E4
)
select @VaccID
, @Clinic
, DATEADD(dd, t.N, @DateStartTime)
, DATEADD(dd, t.N, @DateEndTime)
, @Enroll
, @SignUp
, @BlnAct
, @BlnDis
from cteTally t
where t.N < = DATEDIFF(day, @DateStartTime, @EndDate)
and DATENAME(weekday, DATEADD(dd, t.N, @DateStartTime)) not in ('Saturday', 'Sunday');
@JBBeginner:更正您的查询,
Begin Tran
Declare @VaccID int = 26
Declare @Clinic int = 36
Declare @Enroll int = 30
Declare @SignUp int = 0
Declare @BlnAct int = 1
Declare @BlnDis int = 1
Declare @DateStartTime datetime = '2015-09-16 11:00:00.000'
Declare @DateEndTime datetime = '2015-09-16 14:00:00.000'
Declare @EndDate date = '2015-10-16'
Declare @Days int = DATEDIFF(dd, @DateStartTime, @EndDate)
Select @DateStartTime, @DateEndTime, @Days
Declare @i int = 0
Declare @WeekDay varchar = DAYOFWEEK(dw, @DateStartTime) -- changed
WHILE @i <= @Days
Begin -- changed
IF(@WeekDay = 'Monday' OR
@WeekDay = 'Tuesday' OR
@WeekDay = 'Wednesday' OR
@WeekDay = 'Thursday' OR
@WeekDay = 'Friday')
Begin
INSERT INTO dbo.tblSessions
([intVaccID],
[intLocationID],
[dtDateTimeStart],
[dtDateTimeStop],
[intEnrollmentMax],
[intSignedUp],
[blnActive],
[blnDisplay])
Values (@VaccID,
@Clinic,
DATEADD(dd, @i, @DateStartTime),
DATEADD(dd, @i, @DateEndTime),
@Enroll,
@SignUp,
@BlnAct,
@BlnDis)
SELECT @VaccID as intVaccID,
@Clinic as intLocationID,
DATEADD(dd, @i, @DateStartTime) as dtDateTimeStart,
DATEADD(dd, @i, @DateEndTime) as dtDateTimeStop,
@Enroll as intEnrollmentMax,
@SignUp as intSignedUp,
@BlnAct as blnActive,
@BlnDis as blnDisplay
SET @i = @i + 1
SET @WeekDay = DAYOFWEEK(dw, DATEADD(dd, @i, @DateStartTime))
END
END -- changed
--Rollback Tran -- changed
Commit Tran
递归 CTE 也适用于日期:
Declare @DateStartTime datetime = '2015-09-16 11:00:00.000'
Declare @DateEndTime datetime = '2015-09-16 14:00:00.000'
Declare @EndDate date = '2015-10-16'
;WITH cteDates AS (
SELECT @DateStartTime AS StartDate, @DateEndTime AS EndDate, DATENAME(weekday, @DateStartTime) AS NameOfDay
UNION ALL
SELECT DATEADD(day, 1, cteDates.StartDate), DATEADD(day, 1, cteDates.EndDate), DATENAME(weekday, DATEADD(day, 1, cteDates.StartDate)) AS NameOfDay
FROM cteDates
WHERE DATEADD(day, 1, cteDates.StartDate) <= '2015-10-16'
)
-- INSERT INTO dbo.tblSessions ( ...) -- Omitted for clarity
SELECT * FROM cteDates
WHERE NameOfDay NOT IN ('Saturday', 'Sunday')
过去一个小时我一直在研究这个,但似乎无法让它发挥作用。 我需要做的就是插入这些值,但我需要跳过包含星期六或星期日的插入。
Begin Tran
Declare @VaccID int = 26
Declare @Clinic int = 36
Declare @Enroll int = 30
Declare @SignUp int = 0
Declare @BlnAct int = 1
Declare @BlnDis int = 1
Declare @DateStartTime datetime = '2015-09-16 11:00:00.000'
Declare @DateEndTime datetime = '2015-09-16 14:00:00.000'
Declare @EndDate date = '2015-10-16'
Declare @Days int = DATEDIFF(dd, @DateStartTime, @EndDate)
Select @DateStartTime, @DateEndTime, @Days
Declare @i int = 0
Declare @WeekDay varchar = ''
WHILE @i <= @Days
IF(@WeekDay = 'Monday' OR
@WeekDay = 'Tuesday' OR
@WeekDay = 'Wednesday' OR
@WeekDay = 'Thursday' OR
@WeekDay = 'Friday')
Begin
INSERT INTO dbo.tblSessions
([intVaccID],
[intLocationID],
[dtDateTimeStart],
[dtDateTimeStop],
[intEnrollmentMax],
[intSignedUp],
[blnActive],
[blnDisplay])
Values (@VaccID,
@Clinic,
DATEADD(dd, @i, @DateStartTime),
DATEADD(dd, @i, @DateEndTime),
@Enroll,
@SignUp,
@BlnAct,
@BlnDis)
SELECT @VaccID as intVaccID,
@Clinic as intLocationID,
DATEADD(dd, @i, @DateStartTime) as dtDateTimeStart,
DATEADD(dd, @i, @DateEndTime) as dtDateTimeStop,
@Enroll as intEnrollmentMax,
@SignUp as intSignedUp,
@BlnAct as blnActive,
@BlnDis as blnDisplay
SET @i = @i + 1
SET @WeekDay = DAYOFWEEK(dw, DATEADD(dd, @i, @DateStartTime))
END
Rollback Tran
Commit Tran
它至少在一周的每一天都在填写,但现在似乎在查询中途停滞不前。我知道我错过了一些可笑的小东西,但我似乎无法找到它。我想这是我今天的白鲸。
为什么不使用 GOTO 关键字跳过星期六和星期日:
实际上您的查询应该以其他方式重构。但是对于上面的场景你可以使用这个。
WHILE @i< @days
BEGIN
LABEL :
SET @i = @i + 1
SET @WeekDay = DAYOFWEEK(dw, DATEADD(dd, @i, @DateStartTime))
IF(@WeekDay = 'SATURDAY' OR @WeekDay = 'SUNDAY')
GOTO LABEL
END
您应该将其作为基于集合的操作来执行,而不是使用循环。使用计数 table 时无需循环。看看这是否不会产生所需的输出。
Declare @VaccID int = 26
, @Clinic int = 36
, @Enroll int = 30
, @SignUp int = 0
, @BlnAct int = 1
, @BlnDis int = 1
, @DateStartTime datetime = '2015-09-16 11:00:00.000'
, @DateEndTime datetime = '2015-09-16 14:00:00.000'
, @EndDate date = '2015-10-16';
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM E4
)
select @VaccID
, @Clinic
, DATEADD(dd, t.N, @DateStartTime)
, DATEADD(dd, t.N, @DateEndTime)
, @Enroll
, @SignUp
, @BlnAct
, @BlnDis
from cteTally t
where t.N < = DATEDIFF(day, @DateStartTime, @EndDate)
and DATENAME(weekday, DATEADD(dd, t.N, @DateStartTime)) not in ('Saturday', 'Sunday');
@JBBeginner:更正您的查询,
Begin Tran
Declare @VaccID int = 26
Declare @Clinic int = 36
Declare @Enroll int = 30
Declare @SignUp int = 0
Declare @BlnAct int = 1
Declare @BlnDis int = 1
Declare @DateStartTime datetime = '2015-09-16 11:00:00.000'
Declare @DateEndTime datetime = '2015-09-16 14:00:00.000'
Declare @EndDate date = '2015-10-16'
Declare @Days int = DATEDIFF(dd, @DateStartTime, @EndDate)
Select @DateStartTime, @DateEndTime, @Days
Declare @i int = 0
Declare @WeekDay varchar = DAYOFWEEK(dw, @DateStartTime) -- changed
WHILE @i <= @Days
Begin -- changed
IF(@WeekDay = 'Monday' OR
@WeekDay = 'Tuesday' OR
@WeekDay = 'Wednesday' OR
@WeekDay = 'Thursday' OR
@WeekDay = 'Friday')
Begin
INSERT INTO dbo.tblSessions
([intVaccID],
[intLocationID],
[dtDateTimeStart],
[dtDateTimeStop],
[intEnrollmentMax],
[intSignedUp],
[blnActive],
[blnDisplay])
Values (@VaccID,
@Clinic,
DATEADD(dd, @i, @DateStartTime),
DATEADD(dd, @i, @DateEndTime),
@Enroll,
@SignUp,
@BlnAct,
@BlnDis)
SELECT @VaccID as intVaccID,
@Clinic as intLocationID,
DATEADD(dd, @i, @DateStartTime) as dtDateTimeStart,
DATEADD(dd, @i, @DateEndTime) as dtDateTimeStop,
@Enroll as intEnrollmentMax,
@SignUp as intSignedUp,
@BlnAct as blnActive,
@BlnDis as blnDisplay
SET @i = @i + 1
SET @WeekDay = DAYOFWEEK(dw, DATEADD(dd, @i, @DateStartTime))
END
END -- changed
--Rollback Tran -- changed
Commit Tran
递归 CTE 也适用于日期:
Declare @DateStartTime datetime = '2015-09-16 11:00:00.000'
Declare @DateEndTime datetime = '2015-09-16 14:00:00.000'
Declare @EndDate date = '2015-10-16'
;WITH cteDates AS (
SELECT @DateStartTime AS StartDate, @DateEndTime AS EndDate, DATENAME(weekday, @DateStartTime) AS NameOfDay
UNION ALL
SELECT DATEADD(day, 1, cteDates.StartDate), DATEADD(day, 1, cteDates.EndDate), DATENAME(weekday, DATEADD(day, 1, cteDates.StartDate)) AS NameOfDay
FROM cteDates
WHERE DATEADD(day, 1, cteDates.StartDate) <= '2015-10-16'
)
-- INSERT INTO dbo.tblSessions ( ...) -- Omitted for clarity
SELECT * FROM cteDates
WHERE NameOfDay NOT IN ('Saturday', 'Sunday')