与 SQL 服务器中的错误日期字段作斗争
Struggling with faulty date fields in SQL Server
我有两个 table,一个 parent table 和一个 child-table。 child table 是垂直设计的 table(意味着它存储 Id
、ParentId
、Property
和 PropertyValue
)。当然 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)
我有两个 table,一个 parent table 和一个 child-table。 child table 是垂直设计的 table(意味着它存储 Id
、ParentId
、Property
和 PropertyValue
)。当然 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)