【问题标题】:MySQL nested JSON column search and compare to with today's dayMySQL 嵌套 JSON 列搜索并与今天进行比较
【发布时间】:2020-06-27 07:22:35
【问题描述】:

我正在使用 MySQL 版本 5.7.28。我有如下 json 数据。

CREATE TABLE `week2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` smallint(1),
  `json` text ,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO week2(id,type,json)
VALUES
    (121,1,'[{"weekdays":"Sunday"},{"weekdays":"Monday"},{"weekdays":"Tuesday"},{"weekdays":"Wednesday"},{"weekdays":"Thursday"},{"weekdays":"Friday"},{"weekdays":"Saturday"}]'),
    (122,1,'[{"weekdays":"Sunday"},{"weekdays":"Monday"}]'),
    (123,2,'[{"start_time":"08:00 AM","end_time":"10:00 PM"}]');

如您所见,json 列具有嵌套的 JSON 数据。所以在这里我想比较今天的一天(这是星期六,我们目前处于开始时间和结束时间之间)

预期结果:

(121,1,'[{"weekdays":"Sunday"},{"weekdays":"Monday"},{"weekdays":"Tuesday"},{"weekdays":"Wednesday"},{"weekdays":"Thursday"},{"weekdays":"Friday"},{"weekdays":"Saturday"}]'),
(123,2,'[{"start_time":"08:00 AM","end_time":"10:00 PM"}]');

【问题讨论】:

标签: mysql sql json mysql-5.7 json-extract


【解决方案1】:

您需要检测出日期名称(1)和时间段(2),并通过OR运算符将这两个条件结合起来结束。

对于(1):使用DAYNAME()函数检测当天的名称,并通过JSON_CONTAINS函数搜索包含工作日键的JSON数据中是否存在。

对于 (2)TIME() 函数和 CASTing 字符串到 TIME 数据类型可能会被用于为 PM 类型的情况添加 12 小时迭代的技巧次。

所以,考虑使用:

SELECT *
  FROM `week2`
 WHERE JSON_CONTAINS(`json`->>'$[*].weekdays', CONCAT('"',DAYNAME( NOW() ),'"')) = 1
    OR
    (
      TIME(ADDTIME(NOW(),"8:00:00")) >=       
      CASE WHEN INSTR(REPLACE(`json`->>'$[0].start_time',"12:00 AM","00:00 AM"),"PM")>0 
           THEN 
                CAST(CONCAT(MOD((TIME_FORMAT(REPLACE(`json`->>'$[0].start_time',"12:00 AM","00:00 AM"), "%T")+12),24),":00 AM") 
                  AS TIME) 
           ELSE
                CAST((REPLACE(`json`->>'$[0].start_time',"12:00 AM","00:00 AM")) AS TIME)
            END    
   AND 
      TIME(ADDTIME(NOW(),"8:00:00")) <=
           CASE WHEN INSTR(REPLACE(`json`->>'$[0].end_time',"12:00 AM","00:00 AM"),"PM")>0 
           THEN 
                CAST(CONCAT(MOD((TIME_FORMAT(REPLACE(`json`->>'$[0].end_time',"12:00 AM","00:00 AM"), "%T")+12),24),":00 AM") 
                  AS TIME) 
           ELSE
                CAST(REPLACE(`json`->>'$[0].end_time',"12:00 AM","00:00 AM") AS TIME)                  
            END)

Demo

【讨论】:

  • 如果我们有时间 [{"start_time":"12:00 AM","end_time":"01:00 PM"}] 它不工作..
  • 没有,但没有问题。考虑this demo,如果TIME(NOW()) 被替换为TIME(ADDTIME(NOW(),"-7:00:00")),则两行都返回,目前取决于格林威治标准时间@VishalTanna。
  • 你可以检查这个 ==> dbfiddle.uk/…"
  • 去掉8前面的加号,如果你想继续前进以便保持在这个区间内consider usingTIME(ADDTIME(NOW(),"16:00:00"))当前 @VishalTanna
  • 现在你可以比较一下:dbfiddle.uk/…dbfiddle.uk/… 它只返回从 [{"start_time":"12:00 AM","end_time":"01:00 PM" 开始的行}]
【解决方案2】:

也许是这样的:

SELECT *,CURRENT_TIME 
  FROM
(SELECT *,JSON_UNQUOTE(JSON_EXTRACT(`json`,'$[0].start_time')) AS st,
       JSON_UNQUOTE(JSON_EXTRACT(`json`,'$[0].end_time')) AS et FROM week2) V 
WHERE (JSON_SEARCH(`json`, 'one', DAYNAME(CURDATE()))  IS NOT NULL
       OR
     CURRENT_TIME hour >= 
      CASE WHEN st LIKE '%AM%' THEN REPLACE(st,' AM',':00') 
            WHEN st LIKE '%PM%' THEN SEC_TO_TIME(TIME_TO_SEC(REPLACE(st,' PM',':00'))+43200)
            END
      AND
      CURRENT_TIME hour <=
      CASE WHEN et LIKE '%AM%' THEN REPLACE(et,' AM',':00') 
            WHEN et LIKE '%PM%' THEN SEC_TO_TIME(TIME_TO_SEC(REPLACE(et,' PM',':00'))+43200)
            END);

第一个查询使用JSON_EXTRACT 提取时间,JSON_UNQUOTE 删除 (") 然后将其作为子查询。

在外部查询中,使用JSON_SEARCH 与今天的DAYNAME(CURDATE()) 比较,找到weekdays 的值;如果JSON_SEARCH 没有找到它,它将返回NULL,因此使用IS NOT NULL 条件。

附加OR 以将CURRENT_TIME 与从json 字段中提取的时间值进行比较。但首先,使用CASE 表达式找出它是AM 还是PM;如果是AM,只需REPLACE AM 与秒针(:00)。如果是PM,请像AM 一样执行REPLACE,然后使用TIME_TO_SEC 将时间值转换为秒,然后添加43200 秒(12 小时)并使用hour:minute:second 再次转换为标准hour:minute:second 格式。

P/S:这是我试图回答但我没有发布它,因为我得到了错误的时间结果。只有当我将CURRENT_TIME 放入小提琴时,我才意识到小提琴时区不同那个我的。另外,我正在本地数据库上进行测试;这是 MariaDB,使用STR_TO_TIME 将字符串转换为时间的结果是不同的。老实说,在我看来,如果这是 MariaDB,我认为查询可能会更短。

【讨论】:

    猜你喜欢
    • 2018-09-16
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 2016-02-16
    • 2012-05-10
    • 2013-04-06
    • 1970-01-01
    • 2019-01-09
    相关资源
    最近更新 更多