PostSQLSQL在mySQL中的date_trunc

Yot*_*ray 18 mysql postgresql

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

我不得不切换到mySQL(5.0)并找到一些日期函数而不是比较缺乏.提取函数似乎很有用,我发现的日期函数解决了我的一些问题,但有没有办法复制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')
Run Code Online (Sandbox Code Playgroud)

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

Cha*_*les 28

提取函数似乎很有用,我发现的日期函数解决了我的一些问题,但有没有办法复制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')
Run Code Online (Sandbox Code Playgroud)

使用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)
Run Code Online (Sandbox Code Playgroud)

虽然它应该在功能上是相同的,但实际上这是在进行比较之前将日期变成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')
Run Code Online (Sandbox Code Playgroud)

另外,请注意MySQL在处理日期范围方面确实很差,即使字段已编入索引.如果你不小心的话,你可能最终会得到全表扫描.


Dmi*_*try 5

晚会晚了,但是...

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

select date_add('1900-01-01', interval TIMESTAMPDIFF(MONTH, '1900-01-01', now()) MONTH);
Run Code Online (Sandbox Code Playgroud)

鉴于以上所述,一个人也可以创建一个函数来照顾其他间隔:

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 ;
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

select date_trunc('quarter', now())
Run Code Online (Sandbox Code Playgroud)