2012-11-12 105 views
4

我试图清理在下面的代码在where子句声明:使用case语句的where子句

SELECT 
    CONVERT(datetime, [UTC_Time_Stamp], 127) AS TimeStamp 
FROM 
    Table 
WHERE 
    CASE 
     WHEN ISDATE([UTC_Time_Stamp]) = 1 
     THEN CONVERT(datetime, [UTC_Time_Stamp], 127) 
     ELSE CAST('1/1/1900' AS datetime) 
    END > CAST('11/09/2012' AS datetime) 
    AND 
     CASE 
      WHEN ISDATE([UTC_Time_Stamp]) = 1 
      THEN CONVERT(datetime, [UTC_Time_Stamp], 127) 
      ELSE CAST('1/1/3000' AS datetime) 
     END < CAST('11/10/2012' as datetime) 
ORDER BY 
    TimeStamp; 

UTC_Time_Stamp被存储为一个字符串,有时是零。我之前在我的where子句中遇到了一个转换错误。我修复了这个问题的建议here,但我觉得必须有一个更简单的方法来达到相同的结果。

+1

是9月11日还是11月9日...... –

+0

11月9日(mm/dd/yyyy)。 – Corsae

回答

3

需要做一个case声明内的转换。 SQL是一种描述性语言,并不保证处理顺序。因此,where子句不一定在其他处理之前发生,即使它在子查询或CTE中。但是,SQL确保case语句中的处理顺序(不包含具有聚合函数的表达式)。

您可以使用子查询简化声明:

select TimeStamp 
FROM (select t.*, 
      Case When ISDATE([UTC_Time_Stamp]) = 1 Then CONVERT(datetime, UTC_Time_Stamp, 127) end) as TimeStamp 
     from Table t 
    ) t 
WHERE coalesce(TimeStamp, cast('1/1/1900' as datetime)) > cast('11/09/2012' as datetime) and 
     coalesce(TimeStamp, cast('1/1/3000' as datetime)) < cast('11/10/2012' as datetime) 
ORDER BY TimeStamp; 

这确实转化为时间戳,有效值。然后可以在外部查询中使用该变量。

我还会鼓励你习惯日期(YYYYMMDD或YYYY-MM-DD)的ANSI标准格式,而不是像'11/10/2012'这样的含糊格式。你可能很清楚这意味着2012-11-10。 。 。或者是2012-10-11。 。 。但格式不明确。

+0

+1感谢周一额头巴掌瞬间! –

+0

+1表示模糊格式。 –

0

它更容易做这样的事情(使用任何转换/条之间,您认为合适的谓语):

SELECT CONVERT(datetime, [UTC_Time_Stamp], 127) as TimeStamp 
FROM (
    select [UTC_Time_Stamp] 
    from Table 
    WHERE ISDATE([UTC_Time_Stamp]) = 1 
) a 
WHERE 
    convert(datetime, [UTC_Time_Stamp], 127) between '11/9/2012' and '11/10/2012' 
ORDER BY TimeStamp; 
1

我喜欢热膨胀系数这一点,或者你也可以做临时表,表变量或像@Derek这样的内联派生表。

基本上,我们要首先抓住正确的数据类型,然后有一个容易得多的时间创建我们的查询:

;with CTE as (
    -- Bring back the column as datetime 
    select case when isdate(UTC_Time_Stamp) = 1 then cast(UTC_Time_Stamp as datetime) end as UTC_Time_Stamp 
    from [Table] 
) 
-- Simple select with the proper datatype 
select convert(varchar(50), UTC_Time_Stamp, 127) as [TimeStamp] 
from CTE 
-- May still need gt and lt functionality 
where UTC_Time_Stamp between cast('11/09/2012' as datetime) and cast('11/10/2012' as datetime) 

好像你正在使用时间戳一些任意小的和大的值当你有非日期时,根据你的比较,这可能是不必要的,所以我删除了它们。

请注意,我在CTE中使用datetime数据类型并进行比较,只将它转换为字符串进行演示。

另请注意,between是包容性的,所以您可能需要返回到单独的>< where子句。