【问题标题】:Does SQL BETWEEN work with string dates?SQL BETWEEN 是否适用于字符串日期?
【发布时间】:2013-12-05 22:43:12
【问题描述】:

我有一个大型 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 数据类型之类的真实日期,还是可以像我在上面对字符串所做的那样工作?如果不是,我想我必须删除 BETWEEN 并用可怕的 >= 和

顺便说一下,上面的每个日期字符串计算都有效,因为我已经单独测试了它们,并且确实得到了 YYYYMMDD 格式的日期。

谢谢

更新 上面的重点是避免在比较字符串时使用 >= 和

@StudyYearID 可以是 [S1,S2,S3 或 S4] 中的任何内容 @WorkGroup 可以是 '1A,1B,1C,1D,1E 到 4E'

抱歉给您带来了困扰

【问题讨论】:

  • pur.StudyYearID 和 @Workgroup 中可能的值是什么?
  • StudyYearID = 'S1',工作组 = '1A'

标签: sql-server string datetime between


【解决方案1】:

您为什么要尝试将日期作为字符串进行比较?日期应该是 DATETIME 对象。目前尚不清楚您在使用 StudyYearID 或 @Workgroup 做什么,但如果需要以其他方式构建日期的一部分,则在进行 BETWEEN 比较之前将其转换为 DATETIME 对象。

如果除了首先将它们构建为字符串之外没有其他方法可以得出您的“介于”值之外,那么至少在比较之前进行转换,如下所示:

    AND (pur.StartDate BETWEEN GETDATE()
                AND CAST(CAST(YEAR(DATEADD(YEAR, 1, GETDATE())) AS varchar) + '-12-31' AS DATETIME))

...与您的其他值相同。

【讨论】:

  • 我没有参考,但你是对的,将字符串日期转换回 DATETIME 会起作用。但是,当涉及到时间组件时,我对 BETWEEN 持怀疑态度。我想从这些日期中删除所有时间以仅比较日期,这就是我使用字符串的原因。
  • 剥离时间,CAST(pur.StartDate AS date)
  • 如果你想剥离时间,这里有几种方法:stackoverflow.com/questions/1177449/… 如果你使用 SQL Server,最简单的可能只是转换为DATE(而不是DATETIME) 2008 年及以后。
  • @Anon 你比我快 26 秒 :)
  • @Fernando68 我的意思是您不必将等式左侧的列转换为剥离时间并尝试将值作为字符串进行比较。
【解决方案2】:

天哪,这里出了很多问题。

  1. 将所有这些日期/日期时间值转换为字符串。不要这样做。日期和日期时间值是日期和日期时间值 - 将它们转换为字符串会导致各种不好的事情,例如缺乏验证、无法使用索引进行搜索或范围扫描、删除各种内置日期函数支持等。

  2. Converting to varchar without length. This is a bad habit and should be avoided so you aren't a victim to silent truncation.

  3. Using BETWEEN for date range queries. You should only do this if the underlying column is DATE, and even then I'd be careful. In order to properly use underlying indexes (that exist today, or that may exist tomorrow), you should use an open-ended date range.

我认为通过避免所有对字符串的转换,此查询更加整洁,并且如果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)
    )
  )

【讨论】:

  • 看!这就是我的意思。 BETWEEN 充满了问题,这就是为什么我放弃并将一切都变成弦乐(左右弦乐)的原因。我确实使用了开放式日期范围,实际上我更喜欢它们,因为它对像我这样的傻瓜“解释得更好”,但老实说 BETWEEN 更整洁。那么为什么我不应该使用 BETWEEN 呢?也许另一个 Stackoverflow 问题。还是谢谢
  • 阅读您的文章后,我现在删除了 BETWEEN。最好是你认识的魔鬼。都好。再次感谢。
【解决方案3】:

是的,转换为 ISO 8601 格式字符串的日期将使用 SQL Server 附带的任何排序规则设置按时间顺序排序。每个人都会问你的问题是,“你到底为什么要在相互比较之前将日期转换为字符串?”

【讨论】:

  • 根据我上面的评论。我正在使用其他列的值“构建”一个日期。那你还能怎么做呢?但当然我应该将字符串日期转换回 DATETIME,然后根据 Mayabelle 的评论进行比较。
猜你喜欢
  • 2021-11-23
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 2011-08-22
  • 2014-08-05
  • 2013-07-12
  • 1970-01-01
  • 2019-01-11
相关资源
最近更新 更多