在SQL Server中遇到错误的日期字段

时间:2015-02-18 09:00:02

标签: sql sql-server database tsql sql-server-2005

我有两个表,一个父表和一个子表。子表是一个垂直设计的表(意味着它存储和IdParentIdPropertyPropertyValue)。当然,PropertyValue可以保存所有类型的数据。

我试图过滤这一套,但我却在错误的日期和空地上挣扎。由于只读访问,我无法创建函数,因此我必须在实际查询中执行所有操作。我尝试使用子查询,但我遇到的问题是我没有从子查询中获得结果以便在外部查询中使用。

到目前为止,我已经得到了这个:

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)

有关如何删除错误日期行并继续使用所需数据集的任何建议吗?

3 个答案:

答案 0 :(得分:2)

试试这个。其他一切似乎都是多余的。您无需在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)

答案 1 :(得分:1)

使用以下表达式替换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)

答案 2 :(得分:0)

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

我尝试了一种不同的方法,使用公共表表达式。下面的查询就像一个魅力。

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)