2012-02-13 74 views
1

我需要将字段过滤为日期,但该字段未输入日期或日期时间。在未输入日期的日期字段上过滤

SELECT champ_save_id, element_id, valeur 
FROM g_champ_save AS cs 
INNER JOIN g_champ AS c ON cs.champ_id = c.champ_id 
WHERE cs.valeur <> '' AND NOT cs.valeur IS NULL 
AND c.champ_code = 'qualif_valide_qualif_fin' 
AND CONVERT(datetime, cs.valeur, 103) <= @filterdate 

它抛出一个错误(Conversion failed when converting datetime from character string),除非我的评论的最后一行。
据我所知,SQL优化器首先在每个valeur字段上执行CONVERT函数,然后在其他条件下过滤,然后进行连接。所以它会尝试CONVERT字段中的“常规”文本,所以它当然不起作用。

我尝试过一个CTE,但它做的事情完全一样。

WITH valeurs AS (
    SELECT champ_save_id, element_id, valeur 
    FROM g_champ_save AS cs 
    INNER JOIN g_champ AS c ON cs.champ_id = c.champ_id 
    WHERE cs.valeur <> '' AND NOT cs.valeur IS NULL 
    AND c.champ_code = 'qualif_valide_qualif_fin' 
    AND ISDATE(convert(datetime, cs.valeur, 103)) = 1 
) 
SELECT * FROM valeurs 
WHERE CONVERT(datetime, valeur, 103) <= @filterdate 

你有什么想法,这将让我切切第一返回一个包含日期字段,然后过滤他们?

该表的设计类似(缩短清晰度):

CREATE TABLE g_champ (
    champ_id int IDENTITY(1,1) NOT NULL, 
    type_id int NOT NULL, -- defines the type : text, checkbox, date, etc 
    champ_code nvarchar(50) NULL, 
    champ_label nvarchar(max) NULL 
) 

CREATE TABLE g_champ_save (
    champ_save_id int IDENTITY(1,1) NOT NULL, 
    champ_id int NOT NULL, 
    element_id int NULL, 
    valeur nvarchar(max) NULL 
) 

感谢

+0

CONVERT(datetime,cs.valeur,103)导致错误。请检查该列中的数据,值应该是datetime,即2012013或某个日期值字符串可以转换为DateTime。 – 2012-02-13 14:06:19

回答

2

我认为你需要使用IsDate

SELECT champ_save_id, element_id, valeur 
FROM g_champ_save AS cs 
INNER JOIN g_champ AS c ON cs.champ_id = c.champ_id 
WHERE cs.valeur <> '' AND NOT cs.valeur IS NULL 
AND c.champ_code = 'qualif_valide_qualif_fin' 
AND CONVERT(datetime, case IsDate(cs.valeur) when 1 then cs.valeur end, 103) 
    <= @filterdate 
+1

+1:虽然这假定OP要忽略任何未能转换的值。似乎更可能(对我)OP应该使用ISDATE()来查找违规记录然后纠正它们,而不是忽略它们? – MatBailie 2012-02-13 14:18:33

+0

从我的理解'ISDATE()'函数将返回true如果该值可以转换为任何格式的日期,所以这仍然可以失败,如果该值不能转换为103日期时间格式 – Lamak 2012-02-13 14:33:18

+0

是的,我试过了,但IsDate()测试美国格式(m/d/y),并且我的日期采用法文/英文格式(d/m/y)。因此31/1/2012不被视为日期。 – thomasb 2012-02-13 15:14:19

0

试试这个:我知道这个工程的MSSQL和MySQL,但不知道什么DB乌尔使用

SELECT champ_save_id, element_id, valeur 
FROM g_champ_save AS cs 
INNER JOIN g_champ AS c ON cs.champ_id = c.champ_id 
WHERE cs.valeur <> '' AND NOT cs.valeur IS NULL 
AND c.champ_code = 'qualif_valide_qualif_fin' 
AND Date(cs.valeur) <= @filterdate 
+0

不能:/''日期'不是一个公认的内置函数名称.'。我使用SQL Server 2005/2008。 – thomasb 2012-02-13 14:06:29

1

尝试的HAVING子句中,并使用IS NOT NULLNOT cs.valeur IS NULL

SET DATEFORMAT dmy; 
GO 
SELECT champ_save_id, element_id, valeur 
    FROM g_champ_save AS cs INNER JOIN g_champ AS c 
     ON cs.champ_id = c.champ_id 
WHERE cs.valeur <> '' AND 
     cs.valeur IS NOT NULL AND 
     c.champ_code = 'qualif_valide_qualif_fin' 
HAVING CONVERT(datetime, cs.valeur, 103) <= @filterdate; 
+0

仍然没有运气...它给我同样的错误。 – thomasb 2012-02-13 15:19:09

+1

@ cosmo0我加了SET DATEFORMAT dmy;它现在有效吗? – 2012-02-13 15:36:16

+0

不,但谢谢你的提示! – thomasb 2012-02-13 15:40:54

0

下面的查询应该做的工作,无需转换错误。注意:无效的时间戳将被忽略。

SELECT 
champ_save_id, element_id, valeur 
FROM 
(
SELECT champ_save_id, element_id, valeur 
FROM g_champ_save AS cs 
INNER JOIN (SELECT c.champ_id FROM g_champ c WHERE c.champ_code = 'qualif_valide_qualif_fin') AS c ON cs.champ_id = c.champ_id 
WHERE cs.valeur <> '' AND NOT cs.valeur IS NULL AND ISDATE(cs.valeur) 
) sub 
WHERE CONVERT(datetime, cs.valeur, 103) <= @filterdate 

更新

做了一些改变,这将返回预期的结果。

SET DATEFORMAT dmy;

SET DATEFORMAT dmy; 

SELECT 
champ_save_id, element_id, valeur, CONVERT(datetime, sub.valeur, 103) 
FROM 
(
SELECT champ_save_id, element_id, valeur 
FROM (SELECT 1 champ_id, 1 champ_save_id, 1 element_id, '30/1/2012' valeur) AS cs 
INNER JOIN (SELECT c.champ_id FROM (SELECT 1 champ_id, 'qualif_valide_qualif_fin' champ_code) c WHERE c.champ_code = 'qualif_valide_qualif_fin') AS c ON cs.champ_id = c.champ_id 
WHERE cs.valeur <> '' AND NOT cs.valeur IS NULL AND ISDATE(cs.valeur) = 1 
) sub 
WHERE CONVERT(datetime, sub.valeur, 103) <= '01/02/2012' 
+0

不,显然子查询和CTE是一样的。 – thomasb 2012-02-13 15:17:14

+0

@ cosmo0我加了'SET DATEFORMAT dmy;'它现在有效吗? – 2012-02-13 15:35:10