ข้อ MySQL ระหว่าง "ไม่รวม?


142

ถ้าฉันเรียกใช้แบบสอบถามด้วยbetweenประโยคดูเหมือนว่าจะไม่รวมค่าสิ้นสุด
ตัวอย่างเช่น:

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

สิ่งนี้จะได้รับผลลัพธ์ทั้งหมดdobตั้งแต่ '2011-01-01' ถึง '2011-01-30'; ข้ามบันทึกที่dobอยู่ '2011-01-31' ทุกคนสามารถอธิบายได้ไหมว่าเพราะเหตุใดแบบสอบถามนี้จึงทำงานเช่นนี้และฉันจะแก้ไขเพื่อรวมระเบียนที่dobเป็น '2011-01-31' ได้อย่างไร (ไม่เพิ่ม 1 ถึงวันที่สิ้นสุดเนื่องจากถูกเลือกโดยผู้ใช้)


Nope ฉันติดตั้ง MySQL ของฉัน (เวอร์ชั่น?) BETWEENรวมอยู่ในค่าทั้งสองแล้ว ฉันมีMySQL Server 5.7ใน Windows 10
Green

คำตอบ:


181

ฟิลด์dobอาจมีองค์ประกอบเวลา

วิธีตัดมันออก:

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

59
แทนที่จะคุณสามารถใช้รวบรัดมากขึ้นCAST(dob AS DATE) DATE(dob)
jkndrkn

11
ในขณะที่งานนี้คุณจะได้รับประสิทธิภาพที่ดีขึ้นโดยใช้>=และแทน< between
David Harkness

112
dob BETWEEN '2011-01-01 00:00:00' AND '2011-01-31 23:59:59คุณจะได้รับประสิทธิภาพที่ดีขึ้นโดยใช้ เนื่องจากDATE(dob)ต้องคำนวณค่าสำหรับแต่ละแถวและไม่สามารถใช้ดัชนีใด ๆ ในฟิลด์นั้นได้
joshuahedlund

2
@joshuahedlund โปรดเพิ่มคำตอบด้วยโซลูชันนี้ นักแสดงไม่ได้เกือบมีประสิทธิภาพ
doc_id

3
@joshuahedlund t > 23:59:59 and t < 24:00:00ที่ทำงานจนกว่าคุณจะมีข้อมูลที่มีเวลา ทำไมจัดการกับการระบุไม่ดีBETWEENเลย? ค่อนข้างทำตามคำแนะนำและการใช้ของเดวิด: WHERE dob >= '2011-01-01' AND dob < '2011-02-01'. ประสิทธิภาพที่ดีที่สุดและใช้งานได้ทุกครั้ง
ไม่แยแส

300

จากคู่มือMySQL :

นี่เทียบเท่ากับนิพจน์ (min <= expr AND expr <= สูงสุด)


3
คู่มือที่เชื่อมโยงในคำตอบนี้แสดงว่าต้องการนักแสดงเมื่อเปรียบเทียบวัตถุ DATE และ DATETIME ดังนั้นฉันเดา @tiagoinu มีคำตอบที่สมบูรณ์ที่สุดในความหมายที่เข้มงวดที่สุด แต่ทั้งคู่ก็พร้อม
Kingsolmn

@jemminger อาจจะเป็นเพราะคำตอบคือจากคู่แข่ง -postgres ผู้ชาย: P
Nawfal

27
ในระยะสั้นคือรวม ... นั่นคือเหตุผลที่คำตอบนี้หิน
Rafael

6
ความคิดเห็นเก่า แต่ฉันต้องการผูกนี้กับแบบสอบถามเฉพาะ "BETWEEN" รวมอยู่ แต่มีวันที่ที่ไม่มีเวลาระบุเบาะถึง 00:00:00 การเปรียบเทียบในช่วงวันที่จะทำให้สูญเสียวันสุดท้าย เรียก DATE (dob) หรือระบุจุดสิ้นสุดของวัน
wintermute92

พวกเขาบอกว่าการฝึกฝนคือทองคำจากกรณีการใช้งานของฉันมันไม่รวมเลยฉันสงสัยว่าทำไมสิ่งนี้ถึงเกิดขึ้นกับฉัน ฉันพยายามและบางครั้งก็ใช้งานไม่ได้ ใช้มันในเขตข้อมูล TIME
Jeffery ThaGintoki

99

ปัญหาคือ 2011-01-31 คือ 2011-01-31 00:00:00 นั่นคือจุดเริ่มต้นของวัน ไม่รวมทุกสิ่งในระหว่างวัน


19
นี่เป็นการอธิบายสิ่งที่เกิดขึ้นจริงและตอบคำถาม
Ivan P

3
หลังจากหลายปีที่ผ่านมาคำตอบนี้ยังดีที่สุด ขอบคุณมาก.
Strabek

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

1
ฉันคิดว่ามันน่าสังเกตว่านี่จะไม่รวมวันที่2011-01-31 23:59:59แต่จะรวมถึงจนถึง2011-01-31 23:59:58 วินาทีสุดท้ายของวันไม่รวมอยู่อาจเป็นเรื่องรอง แต่ใครบางคนจะได้รับประโยชน์จาก
doc_id

1
rahmanisback จาก MySQL Documentation ฉันสามารถยืนยันวินาทีสุดท้ายที่จะถูกรวมเนื่องจาก BETWEEN นั้นรวมอยู่ในทั้งสองวิธี อ้างถึงdev.mysql.com/doc/refman/5.5/en/…
Felype

1
ใช่ @Felype คุณพูดถูก ฉันตรวจสอบตัวเองในฐานข้อมูล mysql มันยังรวมถึง23:59:59ในผลลัพธ์ ดังนั้นทั้งสองวิธีรวม
โชคดี

2
หากdobคอลัมน์เป็นเวลาประทับที่มีความแม่นยำรองวินาทีแล้วจะไม่BETWEENพลาดเหตุการณ์ภายในวินาทีสุดท้ายของวันเว้นแต่จะใช้ '2011-02-01 00:00:00' แทนไหม
ไนโตรเจน

1
-1 2011-01-31 23:59:59.003จะไม่รวมถึง @nitrogen ที่ใช้2011-02-01 000:00:00จะรวมเวลาไม่ถูกต้องในวันที่ 1 กุมภาพันธ์ .... ซึ่งเป็นสาเหตุ>=และ<ควรใช้แทน
ไม่แยแส

6

เขตข้อมูลที่คุณอ้างอิงในแบบสอบถามของคุณเป็นประเภทวันที่หรือประเภทDateTimeหรือไม่

สาเหตุทั่วไปของพฤติกรรมที่คุณอธิบายคือเมื่อคุณใช้ประเภท DateTime ซึ่งคุณควรใช้ประเภท Date จริงๆ นั่นคือหากคุณไม่จำเป็นต้องรู้ว่าเวลาเกิดใครให้ใช้ประเภทวันที่

สาเหตุที่วันสุดท้ายไม่รวมอยู่ในผลลัพธ์ของคุณคือวิธีที่คิวรีนั้นสมมติว่าส่วนเวลาของวันที่ที่คุณไม่ได้ระบุในคิวรีของคุณ

นั่นคือ: ข้อความค้นหาของคุณถูกตีความว่ามีความยาวสูงสุดถึงเที่ยงคืนระหว่าง 2011-01-30 และ 2011-01-31 แต่ข้อมูลอาจมีค่าในภายหลังในวันที่ 2011-01-31

คำแนะนำ: เปลี่ยนฟิลด์เป็นประเภทวันที่หากเป็นประเภท DateTime


4

สวัสดีคำถามนี้ใช้ได้สำหรับฉัน

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'

การแปลงนั้นน่าแปลกใจคือการแก้ปัญหามากมายใน MySQL


10
น่าแปลกที่นี่เป็นสิ่งที่คำตอบที่ยอมรับ (และอีกหลายคน) พูดว่า ... 2 ปีก่อนที่คุณจะทำ
Chris Baker

0

ตั้งวันที่ด้านบนเป็นวันที่ + 1 วันดังนั้นในกรณีของคุณตั้งเป็น 2011-02-01


1
นี่จะรวมเวลาศูนย์อย่างไม่ถูกต้องในวันที่ 1 กุมภาพันธ์ .... ซึ่งเป็นสาเหตุที่BETWEENควรละเว้น แต่>=และ<ควรจะนำมาใช้แทน
ไม่แยแส

0

คุณสามารถเรียกใช้แบบสอบถามเป็น:

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

เช่นเดียวกับคนอื่น ๆ ชี้ให้เห็นถ้าวันที่ของคุณจะถูก hardcoded

ในทางกลับกันหากวันที่อยู่ในตารางอื่นคุณสามารถเพิ่มวันและลบวินาที (หากบันทึกวันที่โดยไม่ใช้สอง / ครั้ง) เช่น:

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

หลีกเลี่ยงการปลดเปลื้องกับdobปีศาจ (เช่นเดียวกับคำตอบที่ยอมรับได้) เพราะนั่นอาจทำให้เกิดปัญหาประสิทธิภาพการทำงานขนาดใหญ่ (เช่นไม่สามารถใช้ดัชนีในdobฟิลด์โดยสมมติว่ามี) แผนการดำเนินการอาจเปลี่ยนจากusing index conditionเป็นusing whereหากคุณทำสิ่งที่ชอบDATE(dob)หรือCAST(dob AS DATE)ดังนั้นควรระวัง!


0

ใน MySql ระหว่างค่าจะถูกรวมดังนั้นเมื่อคุณพยายามที่จะได้รับระหว่าง '2011-01-01' และ '2011-01-31'

มันจะรวมจาก2011-01-01 00:00:00ไม่เกิน2011-01-31 00:00:00 จึงไม่มีอะไรจริงใน 2011-01-31 ตั้งแต่เวลาควรไปจาก2011-01-31 00:00:00 ~ 2011-01-31 23:59:59

สำหรับขอบเขตบนคุณสามารถเปลี่ยนเป็น2011-02-01มันจะได้รับข้อมูลทั้งหมดเกิน2011-01-31 23:59:59

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.