我有一个大型SQL,必须生成一些日期才能使用,并与DATETIME列进行比较,我也将其转换为字符串,以便将字符串与字符串进行比较。但BETWEEN是否可以使用字符串?
即
...
AND ((pur.StudyYearID <= @StudyYear
AND CONVERT(varchar, pur.StartDate, 112) BETWEEN CONVERT(varchar, GETDATE(), 112)
AND CONVERT(varchar, CAST(CAST(YEAR(DATEADD(YEAR, 1, GETDATE())) AS varchar) + '1231' AS DATETIME), 112))
OR (pur.StudyYearID > @StudyYear
AND CONVERT(varchar, pur.StartDate, 112) BETWEEN STR(YEAR(GETDATE()) + SUBSTRING(pur.StudyYearID, 2, 1) - SUBSTRING(@Workgroup, 1, 1)) + '0101'
AND STR(YEAR(GETDATE()) + SUBSTRING(pur.StudyYearID, 2, 1) - SUBSTRING(@Workgroup, 1, 1)) + '1231'))
...
我无法指出它,但我“认为”这是有效的。但是,我对BETWEEN很怀疑。 BETWEEN是否仅适用于DATETIME数据类型等实际日期,还是可以像我上面使用Strings一样工作?如果没有,我认为我必须删除BETWEEN并用dreaded&gt; =和&lt; =替换它,对吗?
顺便说一下上面的每个日期字符串计算都有效,因为我已经单独测试了它们,并且我确实得到了YYYYMMDD格式的日期。
由于
更新 上述要点是避免在比较字符串时使用&gt; =和&lt; =。我想使用BETWEEN,但将DATE作为字符串,因为我想确保我将“苹果与苹果”进行比较。然而,这是“糟糕的编程”,因为我可以简单地使用CAST()来剥离时间并使用BETWEEN,如下所述。
@StudyYearID可以是[S1,S2,S3或S4]的任何内容 @WorkGroup可以是'1A,1B,1C,1D,1E到4E'
的任何内容对不起有困惑
答案 0 :(得分:2)
为什么要尝试将日期比作字符串?日期应该是DATETIME对象。目前还不清楚你在使用StudyYearID或@Workgroup做什么,但是如果日期的一部分需要以其他方式构建,那么在进行BETWEEN比较之前将其转换为DATETIME对象。
如果没有其他方法来提出你的“介于”值之外的其他值,而不是先将它们构建为字符串,那么至少在比较之前进行投射,如下所示:
AND (pur.StartDate BETWEEN GETDATE()
AND CAST(CAST(YEAR(DATEADD(YEAR, 1, GETDATE())) AS varchar) + '-12-31' AS DATETIME))
......与您的其他值相同。
答案 1 :(得分:1)
哦,天哪,这里有很多事情都出错了。
将所有这些日期/日期时间值转换为字符串。不要这样做。日期和日期时间值是日期和日期时间值 - 将它们转换为字符串会导致各种不好的事情,例如缺乏验证,无法使用索引进行搜索或范围扫描,丢弃各种内置日期函数支持等等。 / p>
我认为通过避免对字符串的所有转换,这个查询更加整洁,并且如果StartDate
(今天或将来)上存在索引,也会为索引使用提供更好的搜索。
AND
(
(
pur.StudyYearID <= @StudyYear
AND pur.StartDate >= @d AND
AND pur.StartDate < DATEADD(YEAR, 1, @next_year)
)
OR
(
pur.StudyYearID > @StudyYear
AND pur.StartDate >= DATEADD(YEAR, YEAR(GETDATE())
+ SUBSTRING(pur.StudyYearID, 2, 1) - LEFT(@WorkGroup, 1) - 1900, 0)
AND pur.StartDate < DATEADD(YEAR, 1 + YEAR(GETDATE())
+ SUBSTRING(pur.StudyYearID, 2, 1) - LEFT(@WorkGroup, 1) - 1900, 0)
)
)
答案 2 :(得分:0)
是的,转换为ISO 8601格式的字符串的日期将使用SQL Server附带的任何排序规则设置按时间顺序排序。每个人都会问你的问题是,“为什么世界上你在将日期转换为字符串之前将它们相互比较?”