Php MySQL:在查询中使用特殊正则表达式规则修复时间格式

Php MySQL:在查询中使用特殊正则表达式规则修复时间格式,php,mysql,Php,Mysql,我有一个关于MySQL内部时间域的wierd问题 在数据库中,我们有两个字段:date和time。数据如下所示: +-----------------------+ | date | time | +-----------------------+ |27/04/2017| 11:30 | +-----------------------+ |01/05/2017| 20u | +-----------------------+ |02/05/2017

我有一个关于MySQL内部时间域的wierd问题

在数据库中,我们有两个字段:
date
time
。数据如下所示:

+-----------------------+
|   date   |    time    |
+-----------------------+
|27/04/2017|    11:30   |
+-----------------------+
|01/05/2017|    20u     |
+-----------------------+
|02/05/2017|    20u30   |
+-----------------------+
|03/05/2017|    21h     |
+-----------------------+
UNIX_TIMESTAMP(CONCAT(DATE_FORMAT(STR_TO_DATE(`date`,'%d/%m/%Y'),'%Y-%m-%d'),' ',`time`))
function bo_time($string)
{   
    if(preg_match("/(\d{1,2})(u|h)/Ui",$string, $match))
    {
        $string = sprintf("%s:%s", sprintf('%02d', $match[1]), '00' );
    }
    else if(preg_match("/(\d{1,2})(u|h|\:)(\d{2})/Ui",$string, $match))
    {
        $string = sprintf("%s:%s", sprintf('%02d', $match[1]), ( isset($match[3]) ? sprintf('%02d', $match[3]) : '00' ));
    }

    return $string;
}
这些数据意味着什么?嗯:

  • 20u是20:00
  • 20u30是20:30
  • 21小时是21点
主要的问题是,由于某些原因,我必须保持所有这些数据不变,并且必须找到正确显示数据的解决方案,从这个时间戳或正确的日期或匹配正确的日期

为了让您了解我需要什么,查询的某些旧部分使用的内容如下所示:

+-----------------------+
|   date   |    time    |
+-----------------------+
|27/04/2017|    11:30   |
+-----------------------+
|01/05/2017|    20u     |
+-----------------------+
|02/05/2017|    20u30   |
+-----------------------+
|03/05/2017|    21h     |
+-----------------------+
UNIX_TIMESTAMP(CONCAT(DATE_FORMAT(STR_TO_DATE(`date`,'%d/%m/%Y'),'%Y-%m-%d'),' ',`time`))
function bo_time($string)
{   
    if(preg_match("/(\d{1,2})(u|h)/Ui",$string, $match))
    {
        $string = sprintf("%s:%s", sprintf('%02d', $match[1]), '00' );
    }
    else if(preg_match("/(\d{1,2})(u|h|\:)(\d{2})/Ui",$string, $match))
    {
        $string = sprintf("%s:%s", sprintf('%02d', $match[1]), ( isset($match[3]) ? sprintf('%02d', $match[3]) : '00' ));
    }

    return $string;
}
但这在符合正常的情况下是失败的

我编写了一个PHP函数,用于在代码的某些部分显示适当的时间,如下所示:

+-----------------------+
|   date   |    time    |
+-----------------------+
|27/04/2017|    11:30   |
+-----------------------+
|01/05/2017|    20u     |
+-----------------------+
|02/05/2017|    20u30   |
+-----------------------+
|03/05/2017|    21h     |
+-----------------------+
UNIX_TIMESTAMP(CONCAT(DATE_FORMAT(STR_TO_DATE(`date`,'%d/%m/%Y'),'%Y-%m-%d'),' ',`time`))
function bo_time($string)
{   
    if(preg_match("/(\d{1,2})(u|h)/Ui",$string, $match))
    {
        $string = sprintf("%s:%s", sprintf('%02d', $match[1]), '00' );
    }
    else if(preg_match("/(\d{1,2})(u|h|\:)(\d{2})/Ui",$string, $match))
    {
        $string = sprintf("%s:%s", sprintf('%02d', $match[1]), ( isset($match[3]) ? sprintf('%02d', $match[3]) : '00' ));
    }

    return $string;
}
使用该PHP函数,系统的某些部分工作正常,但在系统的某些部分,我可以按日期/时间在表之间进行匹配,所有内容都会失败并崩溃

我的主要问题是:

有没有一种方法可以像在PHP中那样,在MySQL查询中编写一些用于转换时间的正则表达式

谢谢

如果必须保持所有现有数据不变,是否可以创建一个具有适当日期时间格式的新字段并开始使用它

您可以继续使用PHP函数来转换数据,在某些情况下,您可能希望首先修复这些问题,因为它失败了

我能够用更少的行完成PHP函数所做的工作:

// $time = 20u30
preg_replace(['/[uh]/i','/:(?![0-9]+)/'], [':',':00'], $time);

如果必须保持所有现有数据不变,是否可以创建一个具有适当日期时间格式的新字段并开始使用它

您可以继续使用PHP函数来转换数据,在某些情况下,您可能希望首先修复这些问题,因为它失败了

我能够用更少的行完成PHP函数所做的工作:

// $time = 20u30
preg_replace(['/[uh]/i','/:(?![0-9]+)/'], [':',':00'], $time);

首先,将这项陈述留在争议裁决委员会似乎是完全不合理的。似乎
时间
列有一个规范表示法(例如20:11),您可以调整每个字段,使其仅具有该表示法。如果您这样做了,您就不必创建黑客来解决这种表示废话

现在,关于您要求的解决方案的步骤:

  • 首先,如果你把会议记录删去,它们就隐含着“00”,所以“20u”就是“20u00”。现在,如果您只添加两个零,然后在第五个字符后截断,您将得到一个规范化的元组。例如,“20u”->“20u00”->“20u00”或“20:00”->“20:0000”->“20:00”
  • 其次,似乎小时和分钟之间的分隔符是冒号或拉丁文小写字母u,因此“20:15”是“20u15”。这意味着,如果你只是删除这个字母(第一个、第二个、第四个和第五个字母),你会得到一个规范表示。例如,“20:30”->“2030”或“20u30”->“2030”

作为另一个优势,它甚至不尝试使用正则表达式,因为正则表达式代价高昂且容易出错。但是,它依赖于列内容与您编写的内容完全一致,没有例外。

首先,将此表示形式保留在DB中似乎完全不合理。似乎
时间
列有一个规范表示法(例如20:11),您可以调整每个字段,使其仅具有该表示法。如果您这样做了,您就不必创建黑客来解决这种表示废话

现在,关于您要求的解决方案的步骤:

  • 首先,如果你把会议记录删去,它们就隐含着“00”,所以“20u”就是“20u00”。现在,如果您只添加两个零,然后在第五个字符后截断,您将得到一个规范化的元组。例如,“20u”->“20u00”->“20u00”或“20:00”->“20:0000”->“20:00”
  • 其次,似乎小时和分钟之间的分隔符是冒号或拉丁文小写字母u,因此“20:15”是“20u15”。这意味着,如果你只是删除这个字母(第一个、第二个、第四个和第五个字母),你会得到一个规范表示。例如,“20:30”->“2030”或“20u30”->“2030”

作为另一个优势,它甚至不尝试使用正则表达式,因为正则表达式代价高昂且容易出错。但是,它依赖于栏目内容与您编写的内容完全一致,没有例外。

我创建了一个查询,至少对于您提供给我们的数据来说,它似乎是有效的。它只需要一些逻辑来处理数据的各种边缘情况。我将您的时间数据转换为实际的时间戳时间字符串,然后与日期连接,也转换为ISO格式。有了适当的日期和时间,我们就可以调用此时间戳字符串上的
UNIX\u TIMESTAMP
,以获取所需的数据

SELECT
    date, time, UNIX_TIMESTAMP(CONCAT(date, ' ', time)) AS ts
FROM
(
    SELECT
        CONCAT(RIGHT(date, 4), '-', SUBSTRING(date, 4, 2), '-',
               LEFT(date, 2)) AS date,
        CASE WHEN time REGEXP '.*[uh]$'
             THEN CONCAT(LEFT(time, CHAR_LENGTH(time) - 1), ':00:00')
             ELSE CONCAT(REPLACE(REPLACE(time, 'h', ':'),
                         'u', ':'), ':00') END AS time
    FROM yourTable
) t;
输出:

此处演示:


我创建了一个似乎有效的查询,至少对于您提供给我们的数据是如此。它只需要一些逻辑来处理数据的各种边缘情况。我将您的时间数据转换为实际的时间戳时间字符串,然后与日期连接,也转换为ISO格式。有了适当的日期和时间,我们就可以调用此时间戳字符串上的
UNIX\u TIMESTAMP
,以获取所需的数据

SELECT
    date, time, UNIX_TIMESTAMP(CONCAT(date, ' ', time)) AS ts
FROM
(
    SELECT
        CONCAT(RIGHT(date, 4), '-', SUBSTRING(date, 4, 2), '-',
               LEFT(date, 2)) AS date,
        CASE WHEN time REGEXP '.*[uh]$'
             THEN CONCAT(LEFT(time, CHAR_LENGTH(time) - 1), ':00:00')
             ELSE CONCAT(REPLACE(REPLACE(time, 'h', ':'),
                         'u', ':'), ':00') END AS time
    FROM yourTable
) t;
输出:

此处演示:


20u
。。。这是什么意思?你应该认真考虑清理你的日期数据。将所有日期存储为某种类型的日期/时间列中的日期。我更新我的问题20u是20:00,20u30是20:30,21h是21:00。我无法清理,我的客户希望保留这些数据。这些列的确切定义是什么,包括SQL类型和实际使用的内容?给出示例很好,但这还不足以编写处理所有可能情况的代码…@UlrichEckhardt两列都是VARCHAR,日期列是d/m/Y格式,但时间是