Фильтр по полю даты, не указанному как дата - PullRequest
1 голос
/ 13 февраля 2012

Мне нужно отфильтровать поле как дату, но в поле не указывается дата или дата-время.

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 ]

2 голосов
/ 13 февраля 2012

Я думаю, вам нужно использовать 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 голос
/ 13 февраля 2012

попробуйте в предложении 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;
0 голосов
/ 13 февраля 2012

Следующий запрос должен выполнить работу без ошибок преобразования.Примечание. Неверные метки времени будут игнорироваться.

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 голосов
/ 13 февраля 2012

Попробуйте: я знаю, что это работает для 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...