与 SQL 服务器中的错误日期字段作斗争

Struggling with faulty date fields in SQL Server

我有两个 table,一个 parent table 和一个 child-table。 child table 是垂直设计的 table(意味着它存储 IdParentIdPropertyPropertyValue)。当然 PropertyValue 可以容纳所有类型的数据。

我正在尝试过滤此集合,但我正在为错误的日期和空字段而苦苦挣扎。由于 read-only 访问权限,我无法创建函数,因此我必须在实际查询中完成所有操作。我尝试使用子查询,但我遇到了无法从子查询中获取结果以在外部查询中使用的问题。

到目前为止我得到了这个:

DECLARE @Year Int 
SET @Year = 2015

SELECT
    COUNT(Parent.ID), YEAR(PropertyValue), MONTH(PropertyValue)
FROM        
    Parent
INNER JOIN  
    Child ON Parent.ID = Child.ParentID
WHERE       
    Parent.ID IN (SELECT ParentID
                  FROM Child
                  WHERE Child.Property = 'MyDateField'
                    AND ISDATE(Child.PropertyValue) = 1)
    AND Child.Property = 'MyDateField'
    AND YEAR(Child.PropertyValue) = @Year
GROUP BY 
    YEAR(Child.PropertyValue), MONTH(Child.PropertyValue)

关于如何删除错误的日期行并继续处理所需数据集的任何建议?

将 Child.PropertyValue 替换为以下表达式:

(CASE WHEN ISDATE(Child.PropertyValue) = 1 THEN CAST(Child.PropertyValue AS datetime) ELSE NULL END)

编辑: 这里有查询:

SELECT      COUNT(Parent.ID), YEAR(CASE WHEN ISDATE(Child.PropertyValue) = 1 THEN CAST(Child.PropertyValue AS datetime) ELSE NULL END), MONTH(CASE WHEN ISDATE(Child.PropertyValue) = 1 THEN CAST(Child.PropertyValue AS datetime) ELSE NULL END)
FROM        Parent
INNER JOIN  Child
ON          Parent.ID = Child.ParentID
WHERE       Parent.ID IN (
    SELECT ParentID
    FROM    Child
    WHERE   Child.Property = 'MyDateField'
    AND ISDATE(CASE WHEN ISDATE(Child.PropertyValue) = 1 THEN CAST(Child.PropertyValue AS datetime) ELSE NULL END) = 1
)
AND Child.Property = 'MyDateField'
AND YEAR(CASE WHEN ISDATE(Child.PropertyValue) = 1 THEN CAST(Child.PropertyValue AS datetime) ELSE NULL END) = @Year
GROUP BY YEAR(CASE WHEN ISDATE(Child.PropertyValue) = 1 THEN CAST(Child.PropertyValue AS datetime) ELSE NULL END), MONTH(CASE WHEN ISDATE(Child.PropertyValue) = 1 THEN CAST(Child.PropertyValue AS datetime) ELSE NULL END)

试试这个。其他一切似乎都是多余的。您不需要检查 SELECT- 或 GROUP BY 部分中的日期。您的 IN 语句已包含在 WHERE 子句中。

SELECT
    COUNT(Parent.ID), 
    YEAR(Child.PropertyValue), 
    MONTH(Child.PropertyValue)
FROM        
    Parent
INNER JOIN  
    Child ON Parent.ID = Child.ParentID
WHERE       
    Child.Property = 'MyDateField'
    AND CASE WHEN ISDATE(Child.PropertyValue) = 1 
      THEN YEAR(Child.PropertyValue) END = @Year
GROUP BY 
    YEAR(Child.PropertyValue), MONTH(Child.PropertyValue)

我要感谢 Jesus Lopez、Harsch 和 t-clausen.dk 与我一起思考。虽然上述方法确实消除了 SQL-error,但它并没有给我提供我期望的结果。我相信这是由于 ISDATE() 函数的行为和日期的保存方式(作为文本 dd-mm-yyyy)。我注意到当使用 ISDATE() 时,一个月中第 12 天之后的所有结果都不存在(我认为这是因为 ISDATE 解释了错误的文本格式)

我尝试了一种不同的方法,使用常见的 table 表达式。下面的查询很有魅力。

DECLARE @Year int
SET @Year = 2015;

WITH FilteredResults (ParentId, DateValue) 
AS (
    SELECT  ParentId, CONVERT(DateTime, PropertyValue, 105)
    FROM    Child
    WHERE   Property = 'MyDateField'
    AND     PropertyValue <> ''
)

SELECT   count(*), year(DateValue), month(DateValue) 
FROM     FilteredResults 
WHERE    year(DateValue) = @Year
GROUP BY year(DateValue), month(DateValue)
ORDER BY year(DateValue), month(DateValue)