过滤未键入日期的日期字段

时间:2012-02-13 14:01:18

标签: sql sql-server tsql

我需要将字段过滤为日期,但该字段不是键入日期或日期时间。

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优化器首先在每个CONVERT字段上执行valeur函数,然后对其他条件进行过滤,然后加入。因此,它会尝试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
)

由于

4 个答案:

答案 0 :(得分: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)

HAVING子句中尝试使用IS NOT NULL而不是NOT 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;

答案 2 :(得分:0)

试试这个:我知道这适用于MSSQL和MySQL,但不确定使用什么数据库

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

答案 3 :(得分: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'