我正在尝试清理以下代码中的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
存储为字符串,有时为null。我以前遇到过where子句中的转换错误。我根据这个问题here的建议修正了错误,但我觉得必须有一种更简单的方法来实现相同的结果。
答案 0 :(得分: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;
对于有效值,这会转换为TimeStamp。然后,您可以在外部查询中使用该变量。
我还鼓励您习惯日期(YYYYMMDD或YYYY-MM-DD)的ANSI标准格式,而不是像'11 / 10/2012'这样的模糊格式。你可能很清楚,这意味着2012-11-10。 。 。或者是2012-10-11。 。 。但格式不明确。
答案 1 :(得分:1)
我喜欢CTE,或者您也可以使用临时表,表变量或内联派生表,如@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)
当你有非日期时,似乎你正在使用一些任意小的和大的TimeStamp值,这可能是不必要的比较,所以我删除了它们。
请注意,我在CTE中使用datetime数据类型并进行比较,只将其转换为字符串以进行演示。
另请注意,between
具有包容性,因此您可能需要返回单独的>
和<
where子句。
答案 2 :(得分:0)
这样做更容易(使用你认为合适的谓词中的convert / between子句):
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;
答案 3 :(得分:0)
这次对我来说,这解决了使用临时表别名的问题 或子查询会减慢选择数百万条记录的速度。
select your_column
from your_table
where case when ISDATE(your_column) = 1
then Cast(your_column as date)
end Between '01/01/2016' and '01/01/2017'
order by your_column
致谢