MySQL giữa các điều khoản không bao gồm?


142

Nếu tôi chạy một truy vấn với một betweenmệnh đề, nó dường như loại trừ giá trị kết thúc.
Ví dụ:

select * from person where dob between '2011-01-01' and '2011-01-31'

Điều này nhận được tất cả các kết quả dobtừ '2011-01-01' đến '2011-01-30'; bỏ qua hồ sơ trong đó doblà '2011-01-31'. Bất cứ ai cũng có thể giải thích tại sao truy vấn này hoạt động theo cách này và làm thế nào tôi có thể sửa đổi nó để bao gồm các bản ghi trong đó dob'2011-01-31'? (không thêm 1 vào ngày kết thúc vì được người dùng chọn.)


Không. Tôi cài đặt MySQL (phiên bản?) BETWEENBao gồm cả hai giá trị. Tôi có MySQL Server 5.7trên Windows 10.
Green

Câu trả lời:


181

Cánh đồng dob có thể có một thành phần thời gian.

Để cắt nó ra:

select * from person 
where CAST(dob AS DATE) between '2011-01-01' and '2011-01-31'

59
Thay vì CAST(dob AS DATE)bạn có thể sử dụng ngắn gọn hơn DATE(dob).
jkndrkn

11
Trong khi điều này hoạt động, bạn sẽ có hiệu suất tốt hơn bằng cách sử dụng >=<thay vì between.
David Harkness

112
Bạn sẽ có được hiệu suất tốt hơn bằng cách sử dụng dob BETWEEN '2011-01-01 00:00:00' AND '2011-01-31 23:59:59. Điều này là do DATE(dob)phải tính toán một giá trị cho mỗi hàng và không thể sử dụng bất kỳ chỉ mục nào trên trường đó.
joshuahedlund

2
@joshuahedlund Vui lòng thêm câu trả lời với giải pháp này. CAST không phải là gần như hiệu quả.
doc_id

3
@joshuahedlund Điều đó hoạt động cho đến khi bạn có dữ liệu với thời gian t > 23:59:59 and t < 24:00:00. Tại sao đối phó với chỉ định kém BETWEENở tất cả? Thay vì làm theo lời khuyên của David và sử dụng : WHERE dob >= '2011-01-01' AND dob < '2011-02-01'. Hiệu suất tốt nhất, và nó hoạt động mọi lúc.
vỡ mộng

300

Từ hướng dẫn sử dụng MySQL :

Điều này tương đương với biểu thức (min <= expr AND expr <= max)


3
Hướng dẫn được liên kết trong câu trả lời này cho thấy rằng một diễn viên được ưa thích khi so sánh các đối tượng DATE và DATETIME. Vì vậy, tôi đoán @tiagoinu có câu trả lời đầy đủ nhất theo nghĩa chặt chẽ nhất, nhưng cả hai đều được chú ý.
Kingsolmn

@jemminger có thể là do câu trả lời là từ archrival -postgres chàng trai: P
nawfal

27
Tóm lại là bao gồm ... đó là lý do tại sao câu trả lời này đá.
Rafael

6
Nhận xét cũ, nhưng tôi muốn buộc nó vào truy vấn cụ thể. "GIỮA" là bao gồm, nhưng ngày không có thời gian cụ thể đến 00:00:00. So sánh trên một phạm vi ngày sẽ mất ngày cuối cùng. Hoặc gọi DATE (dob) hoặc chỉ định cuối ngày.
wintermute92

họ nói rằng thực tế là vàng, từ trường hợp sử dụng của tôi nó không bao gồm tất cả, tôi tự hỏi tại sao điều này xảy ra với tôi. Tôi đã thử và đôi khi nó hoạt động đôi khi không. sử dụng nó trên trường dữ liệu TIME.
Jeffery ThaGintoki

99

Vấn đề là 2011-01-31 thực sự là 2011-01-31 00:00:00. Đó là sự khởi đầu của ngày. Tất cả mọi thứ trong ngày không được bao gồm.


19
Điều này thực sự giải thích những gì đang xảy ra và trả lời câu hỏi.
Ivan P

3
Sau tất cả những năm đó, câu trả lời này vẫn là tốt nhất. Cảm ơn rất nhiều.
Strabek

30
select * from person where dob between '2011-01-01 00:00:00' and '2011-01-31 23:59:59'

1
Tôi nghĩ rằng đáng chú ý rằng, điều này sẽ không bao gồm ngày tại 2011-01-31 23:59:59nhưng sẽ bao gồm những ngày đến 2011-01-31 23:59:58 giây cuối cùng của ngày không được bao gồm Nó có thể là nhỏ nhưng ai đó sẽ được hưởng lợi.
doc_id

1
rahmanisback từ Tài liệu MySQL Tôi có thể xác nhận SILL thứ hai cuối cùng được bao gồm vì bao gồm cả hai cách. tham khảo dev.mysql.com/doc/refman/5.5/vi/
Felype

1
Vâng, @Felype bạn đúng. Tôi đã tự kiểm tra điều này trong cơ sở dữ liệu mysql. Nó cũng bao gồm 23:59:59trong kết quả. Vì vậy, cả hai cách bao gồm.
May mắn

2
Nếu dobcột là dấu thời gian có độ chính xác dưới giây, thì bạn BETWEENvẫn không bỏ lỡ các sự kiện trong giây cuối cùng của ngày trừ khi '2011 / 02-01 00:00:00' được sử dụng thay thế?
nitơ

1
-1. Sẽ không bao gồm 2011-01-31 23:59:59.003. @nitrogen sử dụng 2011-02-01 000:00:00sẽ không chính xác bao gồm thời gian 0 vào ngày 1 tháng 2 .... Đó là lý do >=<nên được sử dụng thay thế.
vỡ mộng

6

Là trường bạn đang tham chiếu trong truy vấn của mình là loại Ngày hay DateTime loại ?

Một nguyên nhân phổ biến của hành vi bạn mô tả là khi bạn sử dụng loại DateTime nơi bạn thực sự nên sử dụng loại Ngày. Đó là, trừ khi bạn thực sự cần biết thời gian ai đó được sinh ra, chỉ cần sử dụng loại Ngày.

Lý do ngày cuối cùng không được đưa vào kết quả của bạn là cách truy vấn giả định phần thời gian của ngày mà bạn không chỉ định trong truy vấn của mình.

Đó là: Truy vấn của bạn đang được hiểu là đến nửa đêm trong khoảng thời gian từ 2011-01-30 đến 2011-01-31, nhưng dữ liệu có thể có giá trị sau đó trong ngày vào ngày 2011-01-31.

Gợi ý: Thay đổi trường thành loại Ngày nếu đó là loại DateTime.


4

Xin chào truy vấn này làm việc cho tôi,

select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'

2
select * from person where DATE(dob) between '2011-01-01' and '2011-01-31'

Đáng ngạc nhiên là các chuyển đổi như vậy là giải pháp cho nhiều vấn đề trong MySQL.


10
Đáng ngạc nhiên, đây chính xác là những gì câu trả lời được chấp nhận (và một số người khác) đã nói ... 2 năm trước khi bạn làm.
Chris Baker

0

Đặt ngày trên thành ngày + 1 ngày, vì vậy, trong trường hợp của bạn, hãy đặt nó thành 2011 / 02-01.


1
Điều này sẽ không chính xác bao gồm thời gian 0 vào ngày 1 tháng 2 .... Đó là lý do tại sao BETWEENnên bỏ qua; nhưng >=<nên được sử dụng thay thế.
vỡ mộng

0

Bạn có thể chạy truy vấn như:

select * from person where dob between '2011-01-01' and '2011-01-31 23:59:59'

như những người khác đã chỉ ra, nếu ngày của bạn bị mã hóa cứng.

Mặt khác, nếu ngày nằm trong một bảng khác, bạn có thể thêm một ngày và trừ đi một giây (nếu ngày được lưu mà không có giây / lần), như:

select * from person JOIN some_table ... where dob between some_table.initial_date and (some_table.final_date + INTERVAL 1 DAY - INTERVAL 1 SECOND)

Tránh thực hiện phôi trên các dobluồng (như trong câu trả lời được chấp nhận), vì điều đó có thể gây ra các vấn đề hiệu suất lớn (như không thể sử dụng một chỉ mục trong dobtrường, giả sử có một chỉ số). Kế hoạch thực hiện có thể thay đổi từ using index conditiontới using wherenếu bạn thực hiện một cái gì đó giống như DATE(dob)hoặc CAST(dob AS DATE), vì vậy hãy cẩn thận!


0

Do đó, trong MySql giữa các giá trị được bao gồm khi bạn cố gắng lấy trong khoảng từ '2011-01-01' và '2011-01-31'

nó sẽ bao gồm từ 2011-01-01 00:00:00tối đa 2011-01-31 00:00:00 do đó không có gì thực sự trong 2011-01-31 vì thời gian của nó phải đi từ2011-01-31 00:00:00 ~ 2011-01-31 23:59:59

Đối với giới hạn trên, bạn có thể thay đổi để 2011-02-01sau đó nó sẽ nhận được tất cả dữ liệu tối đa2011-01-31 23:59:59

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.