【问题标题】:mysql - converting a string column to a date column when parts of date are missingmysql - 当部分日期丢失时将字符串列转换为日期列
【发布时间】:2017-02-06 19:17:47
【问题描述】:

我正在使用一个表格,该表格描述了一组 92 种医学出版物(名称、发布日期、引文、来源、摘要)。

在原始电子表格中,我将 date_published 中的值写为 YYYY-MM-DD。然而,有些出版物当天不见了——他们只有 MM 和 YYYY。为了使每一行的该列的字符数保持一致,我用 00 替换了缺失的日期(即:2014-09-00)。

Mysql 对 DATE 数据类型中的 00 不满意,并拒绝正确导入我的 csv。因此,我将该列的数据类型更改为 VARCHAR,然后它完美地导入了所有内容。

我想将 date_published 列中的所有内容从 VARCHAR 转换为 DATE。如何让mysql将00天视为null,但仍能正确解释月份和年份?

编辑:一些出版物指定了它们的发布日期,但大多数没有。如果他们这样做,我需要记录下来。如果他们不这样做,我不能只是弥补一天(比如用 01 替换 00 以使其成为有效的 YYYY-MM-DD 条目)。这是一个学术网站,他们对研究的发布日期非常挑剔。

【问题讨论】:

  • 事情就是这样。日期数据类型将仅存储有效日期。如您所见,00 不是有效日期。因此,为月/年组合选择一个有效的日子,你就很好了。如果您不想显示“日”,请添加一个指定日期字段精度的列。然后,当您显示日期时,如果预置是“月”,则格式化输出以排除日期。比如date_format(DateField,%M %Y)所以你得到2017年2月并且日期字符是“隐藏的”。使用 3 个字段并将日期加 1 与 00 和格式输出结合起来 date_format(to_date('2017-02-01'),%M %Y)
  • 作为替代使用 3 个日期字段并显示已填充的字段。因此,在某些没有列出月份、日期的情况下为 2017 年,对于一些没有列出日期的情况,为 2016 年 9 月,对于列出日期的情况,为 2016 年 9 月 28 日;但随后您会丢失日期验证。如果其他人可以直接访问数据库,他们可以在其中查询和绕过您的日期格式,IMO 这是唯一的方法。如果他们只能通过 PHP 查询,那么您可以完全控制并将 01 添加到日期并对其进行格式化。
  • 感谢@xQbert,此评论以比我尝试做的更优雅的方式解决了我的问题。我希望我可以将您的评论标记为答案,以便您获得积分。
  • 我不追求分数,我的 cmets 是一种方法而不是最终答案。我建议您在答案中评论您所做的事情并接受它;如果以下内容不能满足您的特定需求。因为你所做的可能会帮助别人!祝你好运!

标签: php mysql date datetime


【解决方案1】:

您可以像这样将 0 直接替换为导入:

LOAD DATA INFILE 'my.csv'
INTO TABLE TABLE_NAME
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(id, column2, column3, @mydate) -- read one of the field to variable
SET mydate = STR_TO_DATE(CONCAT(SUBSTRING_INDEX(@mydate, '-', 2),'-', 
GREATEST(SUBSTRING_INDEX(@mydate, '-', -1),1)), '%Y-%m-%e');

样本

csv

$ cat my.csv
1,foo,'bar,2017-01-00
2,foo2,'bar2,2016-04-12
3,foo,'bar,2015-08-00

导入

mysql> LOAD DATA INFILE 'my.csv'
    -> INTO TABLE TABLE_NAME
    -> FIELDS TERMINATED BY ','
    -> LINES TERMINATED BY '\n'
    -> (id, column2, column3, @mydate) -- read one of the field to variable
    -> SET mydate = STR_TO_DATE(CONCAT(SUBSTRING_INDEX(@mydate, '-', 2),'-',
    -> GREATEST(SUBSTRING_INDEX(@mydate, '-', -1),1)), '%Y-%m-%e');
Query OK, 3 rows affected (0,00 sec)
Records: 3  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT * FROM table_name;
+----+---------+---------+---------------------+
| id | column2 | column3 | mydate              |
+----+---------+---------+---------------------+
|  1 | foo     | 'bar    | 2017-01-01 00:00:00 |
|  2 | foo2    | 'bar2   | 2016-04-12 00:00:00 |
|  3 | foo     | 'bar    | 2015-08-01 00:00:00 |
+----+---------+---------+---------------------+
3 rows in set (0,00 sec)

mysql>

带有额外列的示例 2

mysql> SELECT * FROM table_name;
Empty set (0,00 sec)

mysql> LOAD DATA INFILE 'my.csv'
    -> INTO TABLE TABLE_NAME
    -> FIELDS TERMINATED BY ','
    -> LINES TERMINATED BY '\n'
    -> (id, column2, column3, @mydate) -- read one of the field to variable
    -> SET haveDay = IF(SUBSTRING_INDEX(@mydate, '-', -1) = 0 , 0 ,1),
    ->
    -> mydate = STR_TO_DATE(CONCAT(SUBSTRING_INDEX(@mydate, '-', 2),'-',
    -> GREATEST(SUBSTRING_INDEX(@mydate, '-', -1),1)), '%Y-%m-%e');
Query OK, 3 rows affected (0,01 sec)
Records: 3  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT * FROM table_name;
+----+---------+---------+---------------------+---------+
| id | column2 | column3 | mydate              | haveDay |
+----+---------+---------+---------------------+---------+
|  1 | foo     | 'bar    | 2017-01-01 00:00:00 |       0 |
|  2 | foo2    | 'bar2   | 2016-04-12 00:00:00 |       1 |
|  3 | foo     | 'bar    | 2015-08-01 00:00:00 |       0 |
+----+---------+---------+---------------------+---------+
3 rows in set (0,00 sec)

mysql>

【讨论】:

  • 除了问题表明 OP 根本不想约会。根据 League14 对 Ken 的回答的第一条评论,将 01 放在日期上是不合适的;但 Aaron 添加额外列的反应是正确的 imo。
  • @xQbert - 是的,我已经为您添加了一个带有额外列的示例。这也将直接由导入填充。
【解决方案2】:

MySQL 不会像这样正确解释日期,而是将 00 替换为 01。 例子; 2014-09-01

【讨论】:

  • 不幸的是,我不能将 00 替换为任何其他可接受的日期整数,因为这对这些出版物来说是欺诈行为。准确显示这项研究的发布时间非常重要。有没有办法可以将 00 注册为 null?
  • @League14 说研究发生在一个月的第 0 天,到底怎么可能更准确?听起来您要么需要添加一个额外的列来指示日期何时为“近似值”,要么您需要停止使用正确的数据类型。
  • @AaronBertrand 无论如何都不准确。这就是为什么我试图让缺少一天的条目的日期为空(而不是 00 或 01)。
  • @League14 我明白了,但是一天不能为 NULL 或 0,所以你需要按照我的建议做些别的事情。
  • 我唯一可以建议的另一件事是将日期分成数据库中的 3 个不同字段,每个字段一个;年/月/日。然后就可以合并 then 进行搜索了。
猜你喜欢
  • 2021-05-09
  • 2011-10-18
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
  • 2016-12-10
  • 2018-07-08
  • 1970-01-01
相关资源
最近更新 更多