2012-03-13 51 views
28

Tôi có trường thời gian ngày trong cơ sở dữ liệu MySQL và muốn xuất kết quả đến giờ gần nhất.MYSQL Ngày giờ đến giờ gần nhất

ví dụ: 2012-04-01 00:00:01 nên đọc 2012-04-01 00:00:00

+0

thể trùng lặp của [Làm thế nào để làm tròn một DateTime trong MySQL?] (Http: // stackoverflow. com/questions/1921362/how-to-round-a-datetime-in-mysql) – Makoto

Trả lời

5

Từ How to round a DateTime in MySQL?:

Đó là một chút khó chịu khi bạn làm điều đó với các kiểu dữ liệu datetime; một ứng cử viên tốt đẹp cho một chức năng được lưu trữ.

DATE_SUB(DATE_SUB(time, INTERVAL MOD(MINUTE(time),5) MINUTE), 
     INTERVAL SECOND(time) SECOND) 

Sẽ dễ dàng hơn khi bạn sử dụng dấu thời gian UNIXTIME nhưng giới hạn trong phạm vi ngày 1970 - 2038.

FROM_UNIXTIME(UNIX_TIMESTAMP(time) - MOD(UNIX_TIMESTAMP(time),300)) 

Chúc may mắn.

+1

Hãy cẩn thận với điều này.Cách tiếp cận thời gian unix không thành công cho các datetimes nằm giữa thay đổi thời gian tiết kiệm ánh sáng ban ngày. Ví dụ: 'chọn FROM_UNIXTIME (UNIX_TIMESTAMP ('2012-03-11 2:14:00') - MOD (UNIX_TIMESTAMP ('2012-03-11 2:14:00'), 300)); ' –

36

Cập nhật: Tôi nghĩ rằng https://stackoverflow.com/a/21330407/480943 là câu trả lời hay hơn.


Bạn có thể làm điều đó với một số ngày số học:

SELECT some_columns, 
    DATE_ADD(
     DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00"), 
     INTERVAL IF(MINUTE(the_date) < 30, 0, 1) HOUR 
    ) AS the_rounded_date 
FROM your_table 

Giải thích:

  • DATE_FORMAT: DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00") trả về ngày cắt ngắn xuống đến giờ gần nhất (đặt phút và phần thứ hai không).

  • MINUTE: MINUTE(the_date) nhận giá trị phút của ngày.

  • IF: Đây là điều kiện; nếu giá trị trong tham số 1 là true, thì nó trả về tham số 2, ngược lại nó trả về tham số 3. Vì vậy, IF(MINUTE(the_date) < 30, 0, 1) có nghĩa là "Nếu giá trị phút nhỏ hơn 30, trả về 0, nếu không trả về 1". Đây là những gì chúng ta sẽ sử dụng để làm tròn - đó là số giờ để thêm vào.

  • DATE_ADD: Điều này sẽ thêm số giờ cho vòng vào kết quả.giải pháp đầu tiên

12

linh hồn của truncates thay vì làm tròn và giải pháp thứ hai không làm việc với các trường hợp Daylight Savings như:

select FROM_UNIXTIME(UNIX_TIMESTAMP('2012-03-11 2:14:00') - MOD(UNIX_TIMESTAMP('2012-03-11 2:14:00'),300)); 

Dưới đây là một phương pháp thay thế (1):

DATE_ADD(
    tick, 
    INTERVAL (IF((MINUTE(tick)*60)+SECOND(tick) < 1800, 0, 3600) - (MINUTE(tick)*60)+SECOND(tick)) SECOND 
) 

Nếu bạn không cần phải lo lắng về giây, bạn có thể đơn giản hóa nó như thế này (2):

DATE_ADD(
    tick, 
    INTERVAL (IF(MINUTE(tick) < 30, 0, 60) - MINUTE(tick)) MINUTE 
) 

Hoặc nếu bạn muốn cắt ngắn thay vì hình tròn, đây là phiên bản đơn giản của phương pháp linh hồn (3):

DATE_SUB(tick, INTERVAL MINUTE(tick)*60+SECOND(tick) SECOND) 

EDIT: Tôi cấu hình một số trong những câu hỏi trên máy tính địa phương của tôi và thấy rằng cho 100.000 hàng các lần trung bình như sau:

  • phương pháp UNIXTIME linh hồn của: 0,0423 ms (nhanh, nhưng không làm việc với DST)
  • phương pháp 3 của tôi: 0,1255 ms
  • phương pháp của tôi 2: 0,1289 DATE_FORMAT phương pháp ms
  • Ben Lee: 0,1495 ms
  • Phương pháp của tôi 1: 0,1506 ms
+0

Đánh dấu từ tôi vì tôi chỉ muốn cắt ngắn – MikeKulls

+0

'DATE_FORMAT' là chậm? Tôi chưa bao giờ nghe về nó. Bạn có tham chiếu/điểm chuẩn cho điều đó không? Tôi không thể tìm thấy bất cứ điều gì trên google về 'DATE_FORMAT' có hiệu suất kém, và không có gì chỉ ra rằng các cuộc gọi đến' MINUTE() 'và' SECOND() 'sẽ nhanh hơn đáng kể so với cuộc gọi đến' DATE_FORMAT'. Trong mọi trường hợp, không nên có sự khác biệt về hiệu suất ở mức độ nano giây - về cơ bản là vô hình/không đáng kể đối với hầu hết mọi mục đích trong thế giới thực? –

+0

@BenLee Tôi mong rằng thao tác chuỗi và phân tích cú pháp ngày sẽ chậm hơn nhiều so với 'MINUTE' /' SECOND', nhưng sau khi lược tả hai trường hợp không đúng. Giải pháp của bạn thậm chí còn có khả năng nhanh hơn một chút so với tôi (có lẽ do tôi gọi 'MINUTE' và' SECOND' hai lần?). Tuy nhiên, ví dụ của tôi bỏ qua giây nhanh hơn 'DATE_FORMAT'. Tôi sẽ cập nhật câu trả lời của mình. –

1

này sẽ trở lại giờ tiếp theo, đó là '2012-01-02 18:02:30' sẽ được chuyển đổi thành '2012-01-02 19:00:00'

TIMESTAMPADD(HOUR, 
    TIMESTAMPDIFF(HOUR,CURDATE(),timestamp_column_name), 
    CURDATE()) 

Thay vì CURDATE() bạn có thể sử dụng một ngày tùy ý, ví dụ '2000-01-01' Không chắc chắn nếu có thể có vấn đề khi sử dụng CURDATE() nếu hệ thống ngày thay đổi giữa hai cuộc gọi đến hàm, không biết nếu Mysql sẽ gọi cả hai cùng một lúc.

để có được những gần giờ sẽ là:

TIMESTAMPADD(MINUTE, 
    ROUND(TIMESTAMPDIFF(MINUTE,CURDATE(),timestamp_column_name)/60)*60, 
    CURDATE()) 

thay đổi 60 15 sẽ nhận được khoảng 15 phút gần nhất, sử dụng thứ hai bạn có thể nhận được khoảng thứ hai mong muốn gần vv

Để sử dụng giờ trước đó TRUNCATE() hoặc FLOOR() thay vì ROUND().

Hy vọng điều này sẽ hữu ích.

20

Nửa giờ là 30 phút. Chỉ cần thêm 30 phút để dấu thời gian và cắt ngắn phút và giây.

SELECT DATE_FORMAT(DATE_ADD(timestamp_column, INTERVAL 30 MINUTE),'%Y-%m-%d %H:00:00') FROM table

0

Nếu bạn cần để làm tròn chỉ thời gian để giờ tiếp theo bạn có thể sử dụng này:

SELECT TIME_FORMAT(
    ADDTIME(
    TIMEDIFF('16:15', '10:00'), '00:59:00' 
), 
    '%H:00:00' 
) 
Các vấn đề liên quan