2011-04-04 73 views
11

最近,我已經熟悉PostgreSQL(使用8.2),並發現date_trunc函數非常有用,可以很容易地在某些天/月/等之間匹配時間戳。 我相信這個函數的實際用處來自於它將輸出保持爲時間戳的格式。PostgreSQL的在mySQL中的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') 

我不知道如何在mySQL中重新創建這樣的規定。所以,我最後的問題是,這種查詢是否可以通過嘗試replicate date_trunc(以及如何)在mySQL中完成,或者是否需要以不同方式查看這些類型的查詢以使其工作在mySQL(和如何做到這一點的建議)?

回答

21

提取函數似乎很有用,我發現的日期函數解決了我的一些問題,但是有什麼方法可以複製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是真正的窮人在處理日期範圍,即使在字段被索引。如果你不小心,你可能最終會進行全表掃描。

3

遲到了,但是......

有一種方法給你認識的時間間隔會被截斷日期。例如,如果時間間隔爲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())