如何添加新年?
How to add new year?
我想在上一学年结束后每次增加学年。例如,我当前的代码如下所示:
WHERE schooldt BETWEEN '07/01/2016' AND '06/30/2017'
所以一旦学年结束 06/30/2017
我想自动设置新的开始日期和新的结束日期。我正在考虑在冷聚变中使用 dateAdd() 。有没有其他方法可以做到这一点,什么方法最有效?
提前致谢。
I would like to increment school year every time after previous school year is over
然后实施根据当前月份更改查询中使用的日期值的逻辑。如果当前月份早于 7 月,则您知道当前学年仍在进行中。所以减去一年来计算开始日期。否则,移至下一年。
<cfset today = now()>
<!--- If the current school year is still in progress --->
<cfif month(today) lt 7>
<cfset startDate = createDate( year(today) - 1, 7, 1)>
<cfset endDate = createDate( year(today), 6, 30)>
<!--- Otherwise, move to next year --->
<cfelse>
<cfset startDate = createDate( year(today), 7, 1)>
<cfset endDate = createDate( year(today) + 1, 6, 30)>
</cfif>
就查询而言,要记住两点:
- 日期字符串不明确。始终使用日期对象。
小心日期比较和 BETWEEN
运算符。如果 SchoolDt
列同时包含日期和时间,则结果可能不是您所期望的。一个更灵活的结构(即使列同时包含日期和时间也仍然有效)是:
WHERE SchoolDt >= <cfqueryparam value="#startDate#" cfsqltype="cf_sql_date">
AND SchoolDt < <cfqueryparam value="#dateAdd('d', 1, endDate)#" cfsqltype="cf_sql_date">
如果您使用 new Query(),请参数化 sql 字符串并改用 addParam
:
yourQuery.addParam( name="startDate"
, value="#startDate#"
, cfsqltype="cf_sql_date" );
yourQuery.addParam( name="endDate"
, value="#endDate#"
, cfsqltype="cf_sql_date" );
日期table答案:
CREATE TABLE calendar (
SeqNum int
, schooldt date NOT NULL PRIMARY KEY
, theYear int
, theMonth tinyint
, theDay tinyint
, schoolyear int
, isSchoolDay tinyint /* Can count schooldays */
, isHoliday tinyint /* Can count holidays. */
)
DECLARE @StartDate date = '1/1/2010'
/* Build tally table with 10^x rows */
; WITH TallyTable (x) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(x) -- 10 days
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(x) -- 100 days
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(x) -- 1000 days
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(x) -- 10000 days
)
INSERT INTO calendar ( SeqNum, schooldt, theYear, theMonth, theDay, schoolyear, isSchoolDay, isHoliday )
SELECT
tt.x AS SeqNum
, d1.theDate
, d2.theYear
, d2.theMonth
, d2.theDay
, d2.theSchoolYear
, 1 , 0 /* Defaults for isSchoolDay and isHoliday. Add if needed. */
FROM TallyTable tt
CROSS APPLY (
SELECT theDate = DATEADD(dd, (tt.x-1), @StartDate) /* Starting date */
) d1
CROSS APPLY
(
SELECT theYear = DATEPART(yy,d1.theDate)
, theMonth = DATEPART(mm,d1.theDate)
, theDay = DATEPART(dd,d1.theDate)
, theSchoolYear = CASE WHEN DATEPART(mm,d1.theDate) < 7 THEN DATEPART(yyyy,d1.theDate) ELSE DATEPART(yyyy,d1.theDate)+1 END
) d2;
沿着这些路线的东西会给你几年后的日子列表。然后你可以加入这个 table 以获得你想要的范围。
要改进 table,您可以包含信息以标记假期和周末,这样您就只能看到学校实际开课的日子。最重要的是,您可以按您希望看到的当前学年过滤所有内容。当需要改变时,您不必担心增加学年。
但这又引出了一个问题,这个查询的最终目标是什么?可能有更好的方法来实现您的最终目标。
我想在上一学年结束后每次增加学年。例如,我当前的代码如下所示:
WHERE schooldt BETWEEN '07/01/2016' AND '06/30/2017'
所以一旦学年结束 06/30/2017
我想自动设置新的开始日期和新的结束日期。我正在考虑在冷聚变中使用 dateAdd() 。有没有其他方法可以做到这一点,什么方法最有效?
提前致谢。
I would like to increment school year every time after previous school year is over
然后实施根据当前月份更改查询中使用的日期值的逻辑。如果当前月份早于 7 月,则您知道当前学年仍在进行中。所以减去一年来计算开始日期。否则,移至下一年。
<cfset today = now()>
<!--- If the current school year is still in progress --->
<cfif month(today) lt 7>
<cfset startDate = createDate( year(today) - 1, 7, 1)>
<cfset endDate = createDate( year(today), 6, 30)>
<!--- Otherwise, move to next year --->
<cfelse>
<cfset startDate = createDate( year(today), 7, 1)>
<cfset endDate = createDate( year(today) + 1, 6, 30)>
</cfif>
就查询而言,要记住两点:
- 日期字符串不明确。始终使用日期对象。
小心日期比较和
BETWEEN
运算符。如果SchoolDt
列同时包含日期和时间,则结果可能不是您所期望的。一个更灵活的结构(即使列同时包含日期和时间也仍然有效)是:WHERE SchoolDt >= <cfqueryparam value="#startDate#" cfsqltype="cf_sql_date"> AND SchoolDt < <cfqueryparam value="#dateAdd('d', 1, endDate)#" cfsqltype="cf_sql_date">
如果您使用 new Query(),请参数化 sql 字符串并改用
addParam
:yourQuery.addParam( name="startDate" , value="#startDate#" , cfsqltype="cf_sql_date" ); yourQuery.addParam( name="endDate" , value="#endDate#" , cfsqltype="cf_sql_date" );
日期table答案:
CREATE TABLE calendar (
SeqNum int
, schooldt date NOT NULL PRIMARY KEY
, theYear int
, theMonth tinyint
, theDay tinyint
, schoolyear int
, isSchoolDay tinyint /* Can count schooldays */
, isHoliday tinyint /* Can count holidays. */
)
DECLARE @StartDate date = '1/1/2010'
/* Build tally table with 10^x rows */
; WITH TallyTable (x) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(x) -- 10 days
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(x) -- 100 days
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(x) -- 1000 days
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d(x) -- 10000 days
)
INSERT INTO calendar ( SeqNum, schooldt, theYear, theMonth, theDay, schoolyear, isSchoolDay, isHoliday )
SELECT
tt.x AS SeqNum
, d1.theDate
, d2.theYear
, d2.theMonth
, d2.theDay
, d2.theSchoolYear
, 1 , 0 /* Defaults for isSchoolDay and isHoliday. Add if needed. */
FROM TallyTable tt
CROSS APPLY (
SELECT theDate = DATEADD(dd, (tt.x-1), @StartDate) /* Starting date */
) d1
CROSS APPLY
(
SELECT theYear = DATEPART(yy,d1.theDate)
, theMonth = DATEPART(mm,d1.theDate)
, theDay = DATEPART(dd,d1.theDate)
, theSchoolYear = CASE WHEN DATEPART(mm,d1.theDate) < 7 THEN DATEPART(yyyy,d1.theDate) ELSE DATEPART(yyyy,d1.theDate)+1 END
) d2;
沿着这些路线的东西会给你几年后的日子列表。然后你可以加入这个 table 以获得你想要的范围。
要改进 table,您可以包含信息以标记假期和周末,这样您就只能看到学校实际开课的日子。最重要的是,您可以按您希望看到的当前学年过滤所有内容。当需要改变时,您不必担心增加学年。
但这又引出了一个问题,这个查询的最终目标是什么?可能有更好的方法来实现您的最终目标。