选择与日期格式不匹配的所有行?

时间:2013-09-06 20:11:31

标签: mysql sql

我正在尝试迁移/更新一个允许在所谓的“日期”字段中存在可空varchar的旧表。我想查找与此格式不匹配的所有行: %e-%b-%y 。我该如何完成此查询?

**编辑:我应该提到该字段确实包含一些“CANCELED”,null或其他字符串值,而不是更常见的e-b-y格式。我正在寻找那些行,所以我可以将它们更新为我想要的格式(%e-%b-%y)。

3 个答案:

答案 0 :(得分:1)

您可以在MySQL中使用正则表达式;见http://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_not-regexp

这是一个表达式,它返回日期字段(dt)为空或不匹配1-2位+破折号+ 3个字母字符+破折号+2位数的行(例如,06-Sep-13)

select * from table_name where dt is null or 
  dt not rlike '[[:digit:]]{1,2}-[[:alpha:]]{3}-[[:digit:]]{2}';

答案 1 :(得分:1)

这是基于comment by Orbling。您可以执行以下操作:

SELECT * FROM my_table
WHERE DATE_FORMAT(CAST(date_field, DATE), '%e-%b-%y') <> date_field

这样做是需要date_field,尝试将其转换为日期,然后将该日期转换回字符串,并与原始字符串进行比较。如果两者不匹配,则报告该行。如果转换失败,您的MySQL客户端可能会报告警告,但您可以放心地忽略这些警告。

这是非常严格检查:它会通过相应地格式化日期来报告无法重新创建完全原始情况的任何行。特别是,这会抱怨前导零,尾随空格等的差异。如果这是一个问题,您可以找到一个不太严格的检查(可能基于日期有效性检查结合一些正则表达式),或者做一些简单的模式匹配来识别和纠正这些行,使它们匹配所需的格式。就像查找匹配__-_-____的所有行并在第一个短划线后引入0一样。

答案 2 :(得分:1)

另一种方法是尝试使用STR_TO_DATE()以不同格式恢复尽可能多的日期,如果提取的值无效则返回NULL,并COALESCE()链接不同的日期格式。

仅显示具有不可恢复日期的行:

SELECT *
  FROM table1
 WHERE COALESCE(STR_TO_DATE(NULLIF(dt, ''), '%e-%b-%Y'),
                STR_TO_DATE(NULLIF(dt, ''), '%e-%b-%y'),
                STR_TO_DATE(NULLIF(dt, ''), '%Y-%m-%d'),
                STR_TO_DATE(NULLIF(dt, ''), '%m/%d/%Y'),
                STR_TO_DATE(NULLIF(dt, ''), '%m/%d/%y')) IS NULL;

看看转换日期后你会得到什么:

SELECT *, COALESCE(STR_TO_DATE(NULLIF(dt, ''), '%e-%b-%Y'),
                   STR_TO_DATE(NULLIF(dt, ''), '%e-%b-%y'),
                   STR_TO_DATE(NULLIF(dt, ''), '%Y-%m-%d'),
                   STR_TO_DATE(NULLIF(dt, ''), '%m/%d/%Y'),
                   STR_TO_DATE(NULLIF(dt, ''), '%m/%d/%y')) new_date
  FROM table1;

注意:

  • 您可以根据需要链接尽可能多的格式字符串。
  • 在两位数%y之前使用四位数格式%y。否则你会得到错误的日期。

如果您要获得以下样本数据:

| ID |          DT |
|----|-------------|
|  1 |   CANCELLED |
|  2 |   02-Mar-12 |
|  3 |      (null) |
|  4 |    5-Aug-13 |
|  5 |             |
|  6 |  2013-09-12 |
|  7 |  10/23/2013 |
|  8 | 13-Aug-2012 |

然后第二个查询产生以下输出:

| ID |          DT |                         NEW_DATE |
|----|-------------|----------------------------------|
|  1 |   CANCELLED |                           (null) |
|  2 |   02-Mar-12 |     March, 02 2012 00:00:00+0000 |
|  3 |      (null) |                           (null) |
|  4 |    5-Aug-13 |    August, 05 2013 00:00:00+0000 |
|  5 |             |                           (null) |
|  6 |  2013-09-12 | September, 12 2013 00:00:00+0000 |
|  7 |  10/23/2013 |   October, 23 2013 00:00:00+0000 |
|  8 | 13-Aug-2012 |    August, 13 2012 00:00:00+0000 |

这是 SQLFiddle 演示