Làm thế nào để chọn ngày từ cột datetime?


238

Tôi có một cột loại "datetime" với các giá trị như 2009-10-20 10:00:00

Tôi muốn trích xuất ngày từ datetime và viết một truy vấn như:

SELECT * FROM 
data 
WHERE datetime = '2009-10-20' 
ORDER BY datetime DESC

Đây có phải là cách tốt nhất để làm điều đó?

SELECT * FROM 
data 
WHERE datetime BETWEEN('2009-10-20 00:00:00' AND '2009-10-20 23:59:59')
ORDER BY datetime DESC

Điều này tuy nhiên trả về một tập kết quả trống. Bất kỳ đề xuất?

Câu trả lời:


455

Bạn có thể sử dụng DATE()chức năng của MySQL :

WHERE DATE(datetime) = '2009-10-20'

Bạn cũng có thể thử điều này:

WHERE datetime LIKE '2009-10-20%'

Xem câu trả lời này để biết thông tin về ý nghĩa hiệu suất của việc sử dụng LIKE.


2
đã thử cái này: Trường hợp DATE (datetime) = '2009-10-20', nó hoạt động
mysqllearner

44
Cái đầu tiên rất chậm và bỏ qua các chỉ mục. Tốt hơn là nên THÍCH 'ngày%'
kachar

NGÀY NÀO (datetime) THÍCH '% keyword%', nó hoạt động, cảm ơn
silvia zulinka

2
Tôi tin rằng điều này không hoạt động như mong đợi nếu múi giờ Rails là một cái gì đó khác với UTC. Điều này là do DATE () giải quyết giá trị cột thành UTC. Vì vậy, một ngày như "Thứ Sáu, ngày 30 tháng 12 năm 2016 00:00:00 SGT +08: 00" mà chúng tôi dự kiến ​​sẽ tìm thấy nếu chúng tôi truy vấn "2016-12-30" sẽ không được tìm thấy. Tại sao? Bởi vì DATE () sẽ giải quyết nó tương đương với UTC của nó trước khi thực hiện so sánh, đó là "2016-12-29 16:00:00 UTC". Sửa lỗi cho tôi nếu tôi sai vì đây cũng là một vấn đề với tôi cho đến gần đây.
Tikiboy

WHERE DATE (datetime) = '{? Sdate} hoạt động hoàn hảo cho tham số Báo cáo Pha lê! Công việc tốt đẹp!
MikeMighty

94

Sử dụng WHERE DATE(datetime) = '2009-10-20' có vấn đề hiệu suất . Như đã nêu ở đây :

  • nó sẽ tính toán DATE()cho tất cả các hàng, kể cả những hàng không khớp.
  • nó sẽ làm cho không thể sử dụng một chỉ mục cho truy vấn.

Sử dụng BETWEENhoặc >, <, =nhà khai thác cho phép sử dụng một chỉ số:

SELECT * FROM data 
WHERE datetime BETWEEN '2009-10-20 00:00:00' AND '2009-10-20 23:59:59'

Cập nhật: các tác động về việc sử dụng LIKEthay vì các nhà khai thác trong một cột được lập chỉ mục là cao . Đây là một số kết quả thử nghiệm trên một bảng có 1.176.000 hàng:

  • sử dụng datetime LIKE '2009-10-20%'=> 2931ms
  • sử dụng datetime >= '2009-10-20 00:00:00' AND datetime <= '2009-10-20 23:59:59'=> 168ms

Khi thực hiện cuộc gọi thứ hai qua cùng một truy vấn, sự khác biệt thậm chí còn cao hơn: 2984ms so với 7ms (vâng, chỉ 7 mili giây!). Tôi đã tìm thấy điều này trong khi viết lại một số mã cũ trên một dự án bằng Hibernate.


Thật thú vị, nếu triển khai MySql tự động chuyển đổi DATE(datetime)để BETWEEN AND xử lý các cảnh chúng ta nhận được tuyên bố ngắn và hiệu suất tuyệt vời. Tại sao không? Tại sao họ không làm điều này? :)
Cherry

Bởi vì một cái gì đó giống như DATE(datetime) in (:list)không hoạt động vớiBETWEEN
Tim

25

Bạn có thể định dạng datetime thành phần YMD:

DATE_FORMAT(datetime, '%Y-%m-%d')

2
Và theo cách này, bạn chỉ có thể nhận được phần thời gian nếu cần:DATE_FORMAT(datetime, '%H:%i:%S')
Metafaniel

điều này hoạt động rất tốt trong việc tạo ra datetime nhưng đổi lại, cơ sở dữ liệu sẽ trả về một mảng mới để đặt tên cho nó chỉ là quảng cáo tên mong muốn ở cuối DATE_FORMAT (cộtName, '% Y-% m-% d') ArrayName để kiểm tra chi tiết hơn tài liệu dev.mysql.com/doc/refman/8.0/vi/ từ
Ridha Rezzag

15

Mặc dù tất cả các câu trả lời trên trang sẽ trả về kết quả mong muốn, nhưng tất cả chúng đều có vấn đề về hiệu suất. Không bao giờ thực hiện các phép tính trên các trường trong WHEREmệnh đề (bao gồm cả DATE()phép tính) vì phép tính đó phải được thực hiện trên tất cả các hàng trong bảng.

Cấu BETWEEN ... ANDtrúc được bao gồm cho cả hai điều kiện biên, yêu cầu một người chỉ định cú pháp 23:59:59 vào ngày kết thúc mà chính nó có vấn đề khác (giao dịch microsecond, mà tôi tin rằng MySQL không hỗ trợ trong năm 2009 khi câu hỏi được hỏi).

Cách thích hợp để truy vấn timestamptrường MySQL cho một ngày cụ thể là kiểm tra xem Lớn hơn so với ngày mong muốn và Ít hơn cho ngày hôm sau, không có giờ nào được chỉ định.

WHERE datetime>='2009-10-20' AND datetime<'2009-10-21'

Đây là phương pháp hiệu suất nhanh nhất, bộ nhớ thấp nhất, ít tốn tài nguyên nhất và cũng hỗ trợ tất cả các tính năng và trường hợp góc của MySQL như độ chính xác của dấu thời gian thứ hai phụ. Ngoài ra, nó là bằng chứng trong tương lai.


1
Và, bằng cách sử dụng đối số hiệu suất của bạn, "> =" và "<" được tính bằng nhau trên mỗi hàng của bảng hay máy chủ SQL chỉ "biết một cách kỳ diệu" nếu một số lớn hơn số khác? :-)
Javier Guerrero

@JavierGuerrero: Ví dụ của tôi so sánh hai hằng số: Một từ bảng và một chuỗi ký tự.
dotancohen

"Một từ bảng" không phải là hằng số, nó thay đổi theo từng hàng, do đó, việc tính toán tương tự phải được thực hiện cho mỗi hàng (và cả hai phải được chuyển đổi thành thời gian kỷ nguyên để thực hiện so sánh)
Javier Guerrero

9

Dưới đây là tất cả các định dạng

Nói đây là cột chứa datetimegiá trị, bảng data.

+--------------------+
| date_created       |
+--------------------+
| 2018-06-02 15:50:30|
+--------------------+

mysql> select DATE(date_created) from data;
+--------------------+
| DATE(date_created) |
+--------------------+
| 2018-06-02         |
+--------------------+

mysql> select YEAR(date_created) from data;
+--------------------+
| YEAR(date_created) |
+--------------------+
|               2018 |
+--------------------+

mysql> select MONTH(date_created) from data;
+---------------------+
| MONTH(date_created) |
+---------------------+
|                   6 |
+---------------------+

mysql> select DAY(date_created) from data;
+-------------------+
| DAY(date_created) |
+-------------------+
|                 2 |
+-------------------+

mysql> select HOUR(date_created) from data;
+--------------------+
| HOUR(date_created) |
+--------------------+
|                 15 |
+--------------------+

mysql> select MINUTE(date_created) from data;
+----------------------+
| MINUTE(date_created) |
+----------------------+
|                   50 |
+----------------------+

mysql> select SECOND(date_created) from data;
+----------------------+
| SECOND(date_created) |
+----------------------+
|                   31 |
+----------------------+

5

Bạn có thể dùng:

DATEDIFF ( day , startdate , enddate ) = 0

Hoặc là:

DATEPART( day, startdate ) = DATEPART(day, enddate)
AND 
DATEPART( month, startdate ) = DATEPART(month, enddate)
AND
DATEPART( year, startdate ) = DATEPART(year, enddate)

Hoặc là:

CONVERT(DATETIME,CONVERT(VARCHAR(12), startdate, 105)) = CONVERT(DATETIME,CONVERT(VARCHAR(12), enddate, 105))

5

cách đơn giản và tốt nhất để sử dụng chức năng ngày

thí dụ

SELECT * FROM 
data 
WHERE date(datetime) = '2009-10-20' 

HOẶC LÀ

SELECT * FROM 
data 
WHERE date(datetime ) >=   '2009-10-20'  && date(datetime )  <= '2009-10-20'

-5

Chà, sử dụng LIKEtrong statement là tùy chọn tốt nhất WHERE datetime LIKE '2009-10-20%' nên hoạt động trong trường hợp này

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.