【问题标题】:CONVERT on only NOT NULL records仅对 NOT NULL 记录进行转换
【发布时间】:2014-10-29 17:16:42
【问题描述】:

我在 SQL Server 2008 中工作。我有一个包含两列存储日期值的表,但列本身是 varchar。 (我知道,这是不好的做法,但我不拥有该表。)这两列中的一些记录是 NULL。我正在尝试对这两列进行比较。所以,为了进行比较,我需要做一个转换。但是,CONVERT 在遇到 NULL 时会失败。我如何从本质上防止 CONVERT 在遇到 NULL 时发生?我的核心查询如下:

SELECT
col1
FROM table_a
WHERE
CONVERT(date, col2, 101) > CONVERT(date, col3, 101)

我尝试了带有 IN 子句的内部查询(即,内部查询仅返回非 NULL 记录),但这失败了,因为查询优化器似乎独立运行这两个查询,即它对所有记录运行 CONVERT ,从而导致失败。我还尝试了自联接(即,仅返回表的第一个实例中的记录,而表的第二个实例中的记录不为空)。但是,由于内部查询场景中的相同问题,这也失败了。

【问题讨论】:

  • where case when col2 is not null then CONVERT(date, col2, 101) end > case when col3 is not null then CONVERT(date, col3, 101) end?
  • 这不起作用。 SQL 抛出以下错误:从字符串转换日期和/或时间时转换失败。我已经验证(通过 ISDATE),对于填充的记录,值确实是日期。
  • 重新转换失败ISDATE is not perfect.
  • 我发现了我的问题。问题出在我的日期值中。对于 col2 和 col3,我必须使用 SUBSTRING 以 YYYY-MM-DD 的形式构造它们。但是,日期样式 101 是 MM/DD/YYYY。所以,我只是更改了我的 SUBSTRING 以生成正确的格式。

标签: sql-server


【解决方案1】:

试试这个:

SELECT
col1
FROM table_a
WHERE 
    case 
    when col2 is null or col3 is null then 0
    when CONVERT(date, col2, 101) > CONVERT(date, col3, 101) then 1
    end = 1

此方法可防止空字符串被转换(或尝试转换),并让您决定如果其中一个或另一个列为空,您可能还想做什么。

编辑:第一个版本在 case 语句中包含语法错误 - 现在应该修复这些错误。为仓促打字而不是 SQLFiddling 道歉。

【讨论】:

  • 这对我不起作用。 SQL 不断抛出错误说明:'>' 附近的语法不正确。
  • @user3100444 我最初在 case 语句中省略了第二个“then”。已编辑,请立即尝试。对不起!
  • 我已经尝试了更新,但仍然无法正常工作(出于同样的原因)。
  • 我不认为 ELSE 可以处理它之后的布尔表达式。不应该是什么时候?
【解决方案2】:

试试这个:(包括示例数据)

DECLARE @TABLE TABLE
 (
    SomeText VARCHAR(50),
    Date01 VARCHAR(50),
    Date02 VARCHAR(50)
)

INSERT INTO @TABLE VALUES('Good Date 01','10/01/2014','12/30/2014')
INSERT INTO @TABLE VALUES('Early Date 01','10/01/2014','12/30/2013')
INSERT INTO @TABLE VALUES('Good Date 02','10/01/2013','10/01/2014')
INSERT INTO @TABLE VALUES('Bad Data 01',NULL,'12/30/2014')
INSERT INTO @TABLE VALUES('Bad Data 02','10/01/2014',NULL)
INSERT INTO @TABLE VALUES('Bad Data 03',NULL,NULL)

SELECT  
    SomeText,
    DATEDIFF(D,CONVERT (DATE, Date01, 101) , CONVERT (DATE, Date02, 101))  AS DELTA
FROM 
    @TABLE 
WHERE
    1 = 1
    AND ISDATE(Date01) = 1 
    AND ISDATE(Date02) = 1 
    and DATEDIFF(D,CONVERT (DATE, Date01, 101) , CONVERT (DATE, Date02, 101)) < 0

ISDATE(Date01) 和 ISDATE(Date02) 将丢失的数据点从转换函数尝试中删除。

【讨论】:

  • 因为优化器的工作原理,我的例子解决了除了无效数据转换如4月31日之外的所有数据问题。如果添加了带有此错误的附加行,则会失败。正在研究如何解决这个问题,而不是将结果返回到从根本上困扰我的辅助临时表。
【解决方案3】:

试试

SELECT * FROM #Tmp
WHERE 
col2 IS NULL OR col3 IS NULL OR 
CONVERT(DATETIME, col2, 101) > CONVERT(DATETIME, col3, 101)

我在 SQL 2005 中尝试过下面的查询,它工作正常,没有任何错误,但它返回的所有记录都没有null。以上查询也返回null记录

SELECT * FROM #Tmp WHERE CONVERT(DATETIME, col2, 101) &gt; CONVERT(DATETIME, col3, 101)

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 2015-04-25
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多