【问题标题】:Can't use BETWEEN for SQL Server dates不能将 BETWEEN 用于 SQL Server 日期
【发布时间】:2017-01-01 06:27:57
【问题描述】:

yyyymmdd 约会让我感到非常痛苦。在此数据库中,null 日期存储为空字符串。

这执行得很好,我可以手动检查日期是否有错误

SELECT 
    effective, expiration 
FROM
    (SELECT 
         CONVERT(date, date_effective, 112) as effective,
         CONVERT(date, date_expiration, 112) as expiration
     FROM ... ) AS X

但是当我想像这样比较它们时:

...
) AS X
WHERE 
    GETDATE() BETWEEN effective AND expiration

这会引发错误

从字符串转换日期和/或时间时转换失败。

我快要淹死了,我花了好几个小时试图让这个日期转换起作用。我担心我唯一的选择是将我想要的东西放入临时表中。日期转换不应该这么难。请帮我转换这些日期并进行比较。

编辑:这个非常大的数据库中有 DIRTY 行,0.003% 的行是坏的

【问题讨论】:

  • 您能否确认您没有任何“脏”行,即不适合 yyyymmdd 或空字符串模式的行?
  • 我不能,我怀疑是这种情况。我会稍微努力一下
  • @SqlOnly BINGO 有脏数据,如何处理?
  • @SqlOnly 我很乐意接受您的评论作为答案,我能够围绕字符串的长度做出 CASE 语句
  • 日期转换应该这么难……很难。尤其是输入数据不好的时候。

标签: sql-server date casting


【解决方案1】:

在不知道日期字符串的确切数据类型(varchar、nvarchar、长度等)的情况下,很难制定一个完美的解决方案。您的问题(和可能的解决方案)也与SO 4384709 非常相似。鉴于这些注意事项,我将采用临时表解决方案(请参阅“@tblCleanDatesAndThings”),如下所示。

--Define a table structure for debugging
DECLARE @tblDatesAndThings TABLE
    (
    date_effective varchar(100) NULL
    ,date_expiration varchar(100) NULL
    )

--Insert some test data
INSERT INTO @tblDatesAndThings
    SELECT '',''  --Bad data (per original question)
    UNION SELECT CONVERT(VARCHAR(100), DATEADD(d, -1, GETDATE())), CONVERT(varchar(100), DATEADD(d,1, GETDATE()))
    UNION SELECT CONVERT(VARCHAR(100), DATEADD(d, -2, GETDATE())), CONVERT(VARCHAR(100), DATEADD(d, 2, GETDATE()))
    UNION SELECT 'a', 'b'  --Bad data (per later edit/comment)

--Define a table structure for clean (or pre-processed) data in our preferred data/output type
DECLARE @tblCleanDatesAndThings TABLE
    (
    date_effective date
    , date_expiration date
    )

--Gather our cleaned up data
INSERT INTO @tblCleanDatesAndThings
    SELECT date_effective,
        date_expiration
    FROM @tblDatesAndThings
        WHERE ISDATE(date_effective) = 1
        AND ISDATE(date_expiration)  = 1

--Apply our criteria to the clean data, for final output
SELECT * FROM @tblCleanDatesAndThings
    WHERE GETDATE() BETWEEN date_effective AND date_expiration

【讨论】:

    【解决方案2】:

    由于您的effectiveexpiration 在字符串YYYYMMDD 中,您只需将GETDATE() 转换为该格式并进行比较。并且effectiveexpiration 列不需要转换

    WHERE CONVERT(VARCHAR(8), GETDATE(), 112) BETWEEN  effective AND expiration
    

    顺便说一句,您应该考虑为这两列使用日期或日期时间数据类型

    【讨论】:

      【解决方案3】:

      SQL Server 可能会感到困惑,因为您试图将DATEDATETIME 进行比较,因为GETDATE() 返回后者。尝试更改转化次数,以便使用 datetime,如下所示:

      CONVERT(datetime, date_effective, 112) as effective
      

      【讨论】:

        【解决方案4】:

        只需与未转换的值进行比较——就像这样

        SELECT effective, expiration 
        FROM
        (
            SELECT 
                CONVERT(date, date_effective, 112) as effective,
                CONVERT(date, date_expiration, 112) as expiration,
                 date_effective, date_expiration
            FROM ...
        ) AS X
        WHERE GETDATE() BETWEEN date_effective AND date_expiration
        

        【讨论】:

          【解决方案5】:
          SELECT 
          CONVERT(date, date_effective, 112) as effective,
          CONVERT(date, date_expiration, 112) as expiration
          FROM ..
          WHERE ISDATE(date_effective) and ISDATE(date_expiration)
          

          【讨论】:

            猜你喜欢
            • 2021-11-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-23
            • 1970-01-01
            • 2019-05-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多