【问题标题】:Extracting ISO dates from a JSON Data type从 JSON 数据类型中提取 ISO 日期
【发布时间】:2017-07-07 09:44:38
【问题描述】:

我正在使用 MySQL json 数据类型来存储 JSON 字符串。 JSON 字符串中有两个字段:entry_timeentry_date。这些字段的值以 ISO 8609 格式存储,如下所示:

entry_date:2017-02-15T00:00:00.00Z
entry_time:0000-00-00T04:35:51.29Z

我正在尝试从这两个属性创建一个虚拟列。由于 MySQL 5.7 设置了NO_ZERO_DATE,我看不到将这些值提取为日期和时间列的方法。这是我尝试过的:

alter table odh
add entry_time time GENERATED ALWAYS AS (REPLACE,(json_extract(jdoc,'$.entry_time')),'0000-00-00T','')

但我也无法完成这项工作。任何帮助将不胜感激!

【问题讨论】:

  • 我建议创建一个规范化的表结构来存储 JSON 数组,然后创建一个 PHP 脚本来将所有数组移动到新表中,并且不再在数据库中存储另一个数组。当然,前面的工作更多,但之后的生活会更轻松。
  • 以 MySQL 的新 JSON 数据类型存储数据有很多好处。

标签: mysql json extract


【解决方案1】:

除了NO_ZERO_DATE 问题之外还有一个另一个问题:MySQL 不使用 ISO 8601 日期,它使用 ISO 9075 或 SQL 日期(实际上它使用各种格式,MySQL 日期处理是相当混乱)。有一些细微的差别,最大的是 9075 中间没有 T。大多数日期 API 通过将 T 设为可选而不是 MySQL 来处理此问题。

mysql> select time('1234-01-01T04:35:51.29Z');
+---------------------------------+
| time('1234-01-01T04:35:51.29Z') |
+---------------------------------+
| 00:12:34                        |
+---------------------------------+
1 row in set, 1 warning (0.00 sec)

MySQL 没有给出错误或忽略 T,而是给出了一些非常错误的答案。

mysql> select time('1234-01-01 04:35:51.29Z');
+---------------------------------+
| time('1234-01-01 04:35:51.29Z') |
+---------------------------------+
| 04:35:51.29                     |
+---------------------------------+
1 row in set, 1 warning (0.00 sec)

现在好了。

最简单的做法是将 T 替换为空格。然后TIME() 就可以了。

mysql> select time(replace('0000-00-00T04:35:51.29Z', 'T', ' '));
+------------------------------------------------+
| time(substring('0000-00-00T04:35:51.29Z', 12)) |
+------------------------------------------------+
| 04:35:51.29                                    |
+------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

日期部分将由 DATE() 处理,因为 MySQL 将忽略其余部分。

mysql> select date('2017-02-15T00:00:00.00Z');
+---------------------------------+
| date('2017-02-15T00:00:00.00Z') |
+---------------------------------+
| 2017-02-15                      |
+---------------------------------+
1 row in set, 1 warning (0.01 sec)

我强烈建议您将它们合并到一个 datetime 列中,而不是存储单独的日期和时间列。特别是如果它们应该代表一个事件(即 2017-20-15 的 4:35:51.29)。这将使比较变得更加容易,并且您始终可以使用DATE()TIME() 提取日期和时间部分。

【讨论】:

    【解决方案2】:

    不确定,但您可能会发现其中一些有用。假设您从数据库中带入的 json 字符串开始:

    $jsonstring = '{
        "entries": [{
            "entry_date": "2017-02-15T00:00:00.00Z",
            "entry_time": "0000-00-00T04:35:51.29Z"
        }, {
            "entry_date": "2017-02-16T00:00:00.00Z",
            "entry_time": "0000-00-00T05:21:08.12Z"
        }, {
            "entry_date": "2017-02-17T00:00:00.00Z",
            "entry_time": "0000-00-00T07:14:55.04Z"
        }]
    }';
    

    以下代码会将其转换为单个字段:

    $json = json_decode($jsonstring, true);
    
    //display the json string before conversion
    echo "<pre>";
    print_r($json['entries']);
    echo "</pre>";
    
    
    $myArray = [];
    for($i = 0; $i < count($json['entries']); $i++) {
        $myArray[] = substr($json['entries'][$i]['entry_date'], 0, 10). 
            substr($json['entries'][$i]['entry_time'], 10);
    }
    //display the json string after conversion
    echo "<pre>";
    print_r($myArray);
    echo "</pre>";
    

    结果将如下所示:

    Array
    (
        [0] => 2017-02-15T04:35:51.29Z
        [1] => 2017-02-16T05:21:08.12Z
        [2] => 2017-02-17T07:14:55.04Z
    )
    

    【讨论】:

    • 此代码不是 SQL。它实际上看起来像 PHP。 OP 对 PHP 只字未提,所以不,这没有帮助。您似乎不了解虚拟生成列的概念。
    猜你喜欢
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    • 2017-10-28
    • 2022-11-30
    • 2020-11-11
    • 2013-10-30
    • 2018-12-12
    • 1970-01-01
    相关资源
    最近更新 更多