【问题标题】:PostgreSQL's date_trunc in mySQLPostgreSQL 在 mySQL 中的 date_trunc
【发布时间】:2011-07-29 07:39:30
【问题描述】:

最近,我熟悉了 PostgreSQL(使用 8.2),发现 date_trunc 函数对于轻松匹配某些天/月/等之间的时间戳非常有用。 我相信,该函数的真正用处在于它将输出保持为时间戳的格式。

我不得不切换到 mySQL(5.0) 并发现一些比较缺乏的日期函数。 extract 函数似乎很有用,我发现的 date 函数解决了我的一些问题,但是有什么方法可以复制 PostgreSQL 的 date_trunc 吗?

以下是我过去如何使用 date_trunc 将查询的时间戳与包括当前月份在内的最近 4 个月匹配的示例,但前提是本月已经过去一周:

WHERE date_trunc('month', QUERY_DATE) BETWEEN 
    date_trunc('month', now()) - INTERVAL '4 MONTH' AND 
    date_trunc('month', now() - INTERVAL '1 WEEK')

我不知道如何在 mySQL 中重新创建这样的规定。所以,我最后的问题是,这种类型的查询是否可以在 mySQL 中通过尝试复制 date_trunc(以及如何)来完成,或者我是否需要以不同的方式开始查看这些类型的查询以使其工作在 mySQL 中(以及如何做到这一点的建议)?

【问题讨论】:

标签: mysql postgresql


【解决方案1】:

extract 函数似乎很有用,我发现的 date 函数解决了我的一些问题,但是有什么方法可以复制 PostgreSQL 的 date_trunc 吗?

确实,EXTRACT 看起来将是这个特定案例最接近的匹配项。

您在 PG 中的原始代码:

WHERE date_trunc('month', QUERY_DATE) BETWEEN 
    date_trunc('month', now()) - INTERVAL '4 MONTH' AND 
    date_trunc('month', now() - INTERVAL '1 WEEK')

使用EXTRACT

WHERE EXTRACT(YEAR_MONTH FROM QUERY_DATE)
      BETWEEN
          EXTRACT(YEAR_MONTH FROM NOW() - INTERVAL 4 MONTH)
      AND
          EXTRACT(YEAR_MONTH FROM NOW() - INTERVAL 1 WEEK)

虽然它应该在功能上相同,但这实际上是在进行比较之前将日期转换为 YYYYMM 字符串。

另一种选择是使用DATE_FORMAT 重建日期字符串并将其强制到月初:

WHERE DATE_FORMAT(QUERY_DATE, '%Y-%m-01')
      BETWEEN
          DATE_FORMAT(NOW() - INTERVAL 4 MONTH, '%Y-%m-01')
      AND
          DATE_FORMAT(NOW() - INTERVAL 1 WEEK, '%Y-%m-01')

另外,请注意 MySQL 在处理日期范围方面确实很差,即使该字段已被索引。如果您不小心,您可能会以全表扫描结束。

【讨论】:

    【解决方案2】:

    派对迟到了,但是……

    如果您知道时间间隔,有一种方法可以截断日期。例如,如果间隔是 MONTH,您可以使用以下命令将今天的日期 (now()) 截断为月份:

    select date_add('1900-01-01', interval TIMESTAMPDIFF(MONTH, '1900-01-01', now()) MONTH);
    

    鉴于上述情况,可以创建一个函数来处理其他间隔:

    DELIMITER //
    create function date_trunc(vInterval varchar(7), vDate timestamp)
    returns timestamp
    begin
        declare toReturn timestamp;
    
        if vInterval = 'year' then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(YEAR, '1900-01-01', vDate) YEAR);
        elseif vInterval = 'quarter' then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(QUARTER, '1900-01-01', vDate) QUARTER);
        elseif vInterval = 'month' then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(MONTH, '1900-01-01', vDate) MONTH);
        elseif vInterval = 'week' then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(WEEK, '1900-01-01', vDate) WEEK);
        elseif vInterval = 'day' then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(DAY, '1900-01-01', vDate) DAY);
        elseif vInterval = 'hour' then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(HOUR, '1900-01-01', vDate) HOUR);
        elseif vInterval = 'minute' then set toReturn = date_add('1900-01-01', interval TIMESTAMPDIFF(MINUTE, '1900-01-01', vDate) MINUTE);
        END IF;
    
        return toReturn;
    end//
    DELIMITER ;
    

    像这样使用它:

    select date_trunc('quarter', now())
    

    【讨论】:

      【解决方案3】:

      这是一个使用@Charles 上面推荐的DATE_FORMAT mysql 函数来模仿postgres 的DATE_TRUNC 合约的函数。

      DROP FUNCTION IF EXISTS DATE_TRUNC;
      CREATE FUNCTION DATE_TRUNC(
        in_granularity ENUM('hour', 'day', 'month', 'year'),
        in_datetime datetime(6)
      )
      RETURNS datetime(6)
      DETERMINISTIC
      BEGIN
        IF (in_granularity = 'hour') THEN
          RETURN DATE_FORMAT(in_datetime, '%Y-%m-%d %H:00:00.0000');
        END IF;
        IF (in_granularity = 'day') THEN
          RETURN DATE_FORMAT(in_datetime, '%Y-%m-%d 00:00:00.0000');
        END IF;
        IF (in_granularity = 'month') THEN
          RETURN DATE_FORMAT(in_datetime, '%Y-%m-01 00:00:00.0000');
        END IF;
        IF (in_granularity = 'year') THEN
          RETURN DATE_FORMAT(in_datetime, '%Y-01-01 00:00:00.0000');
        END IF;
      END;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-23
        • 1970-01-01
        • 2021-03-06
        • 1970-01-01
        • 2020-10-05
        • 1970-01-01
        • 2018-03-07
        相关资源
        最近更新 更多