【问题标题】:Struggling with faulty date fields in SQL Server在 SQL Server 中处理错误的日期字段
【发布时间】:2015-04-19 05:07:37
【问题描述】:

我有两个表,一个父表和一个子表。子表是一个垂直设计的表(意味着它存储和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)

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

【问题讨论】:

  • SQL Server 版本?。如果版本是 2012 及更高版本,您可以使用 TRY_CAST。将 Child.PropertyValue 替换为 TRY_CAST(Child.PropertyValue AS datetime)
  • 不幸的是 2005 年。更新了标签。
  • 内部查询是否返回任何行?
  • 是的,也是所需的行集。
  • 记录在案。语法警察...人们写查询的方式有多种。这只是编辑让你再次出现吗?噗。

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


【解决方案1】:

试试这个。其他一切似乎都是多余的。您不需要检查 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
  • 您的查询看起来确实干净多了。但是,我也得到了错误的结果(与我对耶稣洛佩兹的评论相同)。奇怪,不是吗?它怎么会显示 2015 年 3 月到 2015 年 12 月的结果?此外,计数结果太低了。我还在研究它:)
【解决方案2】:

将 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)

【讨论】:

  • 嗯,我有点迷失在哪里将您的建议放在我的查询中。你能按照你看到的那样放置整个查询吗?已经谢谢了。
  • 完成!我把它换了。我假设 PropertyValue 仅在子表上。
  • 虽然我得到了结果,但他们现在错了。例如,我还获得了 2015 年所有月份的结果,但尚未过去。我认为这与我的查询有关,所以我将深入研究它。现在谢谢! +1 并接受。我也不知道我可以在函数中使用案例。
【解决方案3】:

我要感谢 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)

【讨论】:

    猜你喜欢
    • 2020-09-11
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    相关资源
    最近更新 更多