MySQL so sánh chuỗi DATE với chuỗi từ trường DATETIME


93

Tôi có một câu hỏi: Có thể chọn từ cơ sở dữ liệu MySQL bằng cách so sánh một chuỗi DATE "2010-04-29" với các chuỗi được lưu trữ dưới dạng DATETIME (2010-04-29 10:00) không?

Tôi có một bộ chọn ngày lọc dữ liệu và tôi muốn truy vấn bảng theo trường DATETIME như sau:

SELECT * FROM `calendar` WHERE startTime = '2010-04-29'"

... và tôi muốn nhận hàng có giá trị DATETIME là "2010-04-29 10:00".

Bất kỳ đề xuất? Cảm ơn.

Câu trả lời:


163

Sử dụng như sau:

SELECT * FROM `calendar` WHERE DATE(startTime) = '2010-04-29'

Chỉ để tham khảo, tôi có một bảng ghi 2 triệu, tôi đã chạy một truy vấn tương tự. Câu trả lời của Salils mất 4,48 giây, câu trên mất 2,25 giây.

Vì vậy, nếu bảng là LỚN hơn, tôi sẽ đề xuất điều này.


8
Câu trả lời đầu tiên quá chậm, bởi vì nó phải định dạng mỗi ngày giờ thành một chuỗi trước khi so sánh. Bạn là tốt hơn, vì nó trực tiếp so sánh chỉ là phần cập nhật từ lĩnh vực này, nhưng nó vẫn không thể sử dụng chỉ số (thử nghiệm trên mysql 5.1)
Marki555

1
Nếu hiệu suất là một vấn đề, có thể nên xem xét việc lưu trữ riêng phần ngày và giờ để có thể đặt INDEX trên phần ngày.
Thijs Riezebeek

1
Truy vấn này sẽ không thể sử dụng chỉ mục nếu startTimeđược lập chỉ mục.
Zamrony P. Juhara

43

Nếu bạn muốn chọn tất cả các hàng trong đó phần DATE của cột DATETIME khớp với một chữ nhất định, bạn không thể làm như vậy:

WHERE startTime = '2010-04-29'

vì MySQL không thể so sánh trực tiếp DATE và DATETIME. MySQL làm gì, nó mở rộng chữ DATE đã cho với thời gian '00: 00: 00 '. Vì vậy, tình trạng của bạn trở thành

WHERE startTime = '2010-04-29 00:00:00'

Chắc chắn không phải những gì bạn muốn!

Điều kiện là một phạm vi và do đó nó phải được cung cấp dưới dạng phạm vi. Có một số khả năng:

WHERE startTime BETWEEN '2010-04-29 00:00:00' AND '2010-04-29 23:59:59'
WHERE startTime >= '2010-04-29' AND startTime < ('2010-04-29' + INTERVAL 1 DAY)

Có một khả năng nhỏ là sai lầm đầu tiên - khi cột DATETIME của bạn sử dụng độ phân giải giây con và có một cuộc hẹn lúc 23:59:59 + epsilon. Nói chung, tôi đề nghị sử dụng biến thể thứ hai.

Cả hai biến thể đều có thể sử dụng một chỉ mục trên startTime sẽ trở nên quan trọng khi bảng phát triển.


9
Phiên bản của David không tốt, nó không thể sử dụng các chỉ mục. Để sử dụng một chỉ mục, bạn phải lọc trên cột trực tiếp, chứ không phải vào một kết quả của một hàm ( date(), year(), datediff()hoặc bất kỳ tương tự)
Marki555

Tôi đang tìm kiếm cách mysql chuyển đổi ngày thành datetime, cảm ơn vì đã xóa nó thêm 00:00:00. bây giờ kết quả của tôi có ý nghĩa
Kế toán م

1
Đây là giải pháp nhanh chóng chính xác so với câu trả lời khác mà không thể sử dụng chỉ số nếu có
Zamrony P. Juhara

23
SELECT * FROM `calendar` WHERE DATE_FORMAT(startTime, "%Y-%m-%d") = '2010-04-29'"

HOẶC LÀ

SELECT * FROM `calendar` WHERE DATE(startTime) = '2010-04-29'

25
Đây là một truy vấn khủng khiếp. Tránh điều này bằng mọi giá. Nếu có một chỉ mục trên startTime, nó không thể được sử dụng bởi truy vấn này, vì nó áp dụng một hàm cho cột thay vì sử dụng nó trực tiếp. Điều đó có nghĩa là bất kỳ truy vấn nào như thế này sẽ yêu cầu quét toàn bộ bảng. Trên một bảng lớn, điều này có nghĩa là một truy vấn cực kỳ chậm.
steveayre

Tôi đồng ý, câu trả lời của anh ấy là sai - câu trả lời đúng được David đăng bên dưới.
mindplay.dk

1
Vui lòng sử dụng câu trả lời từ David, vì nó nhanh hơn. Cái này là hợp lệ, nhưng không tốt cho tốc độ ...
xarlymg89

1
@ CarlosAlbertoMartínezGadea Phiên bản này chậm vì phải định dạng từng giá trị thành chuỗi trước khi so sánh ... Phiên bản của David không cần nó, nhưng vẫn không thể sử dụng các chỉ mục, vì vậy không phải là tối ưu. Xem câu trả lời từ XL_ để biết phiên bản có thể sử dụng chỉ mục. Đáng tiếc là không có cách nào tốt hơn để làm điều đó đúng trong mysql
Marki555

1
Tôi đã phản đối câu trả lời này vì truy vấn không thể sử dụng chỉ mục, trong khi câu trả lời của @ XL_ thì có.
pedromanoel

2
SELECT * FROM sample_table WHERE last_visit = DATE_FORMAT('2014-11-24 10:48:09','%Y-%m-%d %H:%i:%s')

này cho định dạng datetime trong mysql bằng cách sử dụng DATE_FORMAT(date,format).


1
SELECT * FROM `calendar` WHERE DATE(startTime) = '2010-04-29';

nó hữu ích, bạn có thể chuyển đổi các giá trị như DATEtrước khi so sánh.


0

Bạn có thể truyền trường DATETIME thành DATE dưới dạng:

SELECT * FROM `calendar` WHERE CAST(startTime AS DATE) = '2010-04-29'

Điều này rất hiệu quả.


1
Không, nó cũng không hiệu quả. điều này sẽ không thể sử dụng chỉ mục nếu startTimeđược lập chỉ mục
Zamrony P. Juhara

-6
SELECT * FROM `calendar` WHERE startTime like '2010-04-29%'

Bạn cũng có thể sử dụng toán tử so sánh trên MySQL ngày nếu bạn muốn tìm thứ gì đó sau hoặc trước đó. Điều này là do chúng được viết theo cách (giá trị lớn nhất đến nhỏ nhất với các số 0 ở đầu) mà một chuỗi sắp xếp đơn giản sẽ sắp xếp chúng một cách chính xác.

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.