MS SQL Server“ อยู่ระหว่าง” รวมขอบเขตช่วงหรือไม่


234

ตัวอย่างเช่นสามารถ

SELECT foo
FROM bar
WHERE foo BETWEEN 5 AND 10

เลือก 5 และ 10 หรือถูกแยกออกจากช่วง

คำตอบ:


258

ผู้ประกอบการระหว่างรวม

จากหนังสือออนไลน์:

ระหว่างผลตอบแทน TRUE ถ้าค่าของ test_expression มากกว่าหรือเท่ากับค่าของ start_expression และน้อยกว่าหรือเท่ากับมูลค่าของ end_expression

วันที่และเวลา Caveat

หมายเหตุ: ด้วย DateTimes คุณจะต้องระมัดระวัง หากมีการกำหนดวันที่เท่านั้นค่าจะถูกนำมาใช้ในเวลาเที่ยงคืนของวันนั้น เพื่อหลีกเลี่ยงเวลาที่หายไปภายในวันที่สิ้นสุดของคุณหรือทำการเก็บข้อมูลของวันถัดไปตอนเที่ยงคืนในหลายช่วงวันที่สิ้นสุดของคุณควรเป็น 3 มิลลิวินาทีก่อนเที่ยงคืนของวันถัดจากวันที่คุณ 3 มิลลิวินาทีเพราะน้อยกว่านี้และค่าจะถูกปัดเศษเป็นเที่ยงคืนของวันถัดไป

เช่นรับค่าทั้งหมดภายในมิถุนายน 2559 คุณต้องเรียกใช้:

where myDateTime between '20160601' and DATEADD(millisecond, -3, '20160701')

กล่าวคือ

where myDateTime between '20160601 00:00:00.000' and '20160630 23:59:59.997'

datetime2 และ datetimeoffset

การลบ 3 ms จากวันที่จะทำให้คุณเสี่ยงต่อแถวที่หายไปจากหน้าต่าง 3 ms โซลูชันที่ถูกต้องเป็นวิธีที่ง่ายที่สุด:

where myDateTime >= '20160601' AND myDateTime < '20160701'

11
เมื่อใช้ระหว่างการกรอง DateTimes ระหว่างวันที่สองวันคุณสามารถแปลง DateTime เป็นวันที่ได้เช่น: ที่ CONVERT (DATE, MyDate) ระหว่าง '2017-09-01' และ '2017-09-30' วิธีนี้ทำให้เวลา องค์ประกอบของ DateTime ที่ไม่เกี่ยวข้อง
Pete

1
อย่าพยายามลบ 3 ms ออกจากวันที่ คุณจะพลาดไอเท็มจาก 3 มิลลิวินาที และคุณยังไม่ต้องการที่จะdatetimeกับวันที่เป็นที่จะทำให้ดัชนีไร้ประโยชน์ ใช้มาตรฐาน นอกจากนี้ให้แน่ใจว่าใช้ตามที่ขึ้นอยู่กับสถานที่และจะตีความผิดขึ้นอยู่กับการตั้งค่าเซิร์ฟเวอร์ของคุณ CONVERTWHERE OrderDate >= '20160601' AND OrderDate < '20160701'yyyymmddyyyy-mm-ddmdy, dmy, ymd, ydm, myd, and dym
Ian Boyd

254

ใช่ แต่ระวังเมื่อใช้ระหว่างวันที่

BETWEEN '20090101' AND '20090131'

ตีความได้ว่าเป็นเวลา 12.00 น. หรือ

BETWEEN '20090101 00:00:00' AND '20090131 00:00:00'

ดังนั้นจะพลาดสิ่งที่เกิดขึ้นระหว่างวันที่ 31 มกราคม ในกรณีนี้คุณจะต้องใช้:

myDate >= '20090101 00:00:00' AND myDate < '20090201 00:00:00'  --CORRECT!

หรือ

BETWEEN '20090101 00:00:00' AND '20090131 23:59:59' --WRONG! (see update!)

UPDATE : เป็นไปได้ทั้งหมดที่จะมีการสร้างบันทึกภายในวินาทีสุดท้ายของวันโดยมีช่วงเวลาที่สั้นที่สุด20090101 23:59:59.997!!

ด้วยเหตุนี้BETWEEN (firstday) AND (lastday 23:59:59)จึงไม่แนะนำวิธีการ

ใช้myDate >= (firstday) AND myDate < (Lastday+1)วิธีการแทน

ดีบทความเกี่ยวกับเรื่องนี้ที่นี่


1
ปัญหาที่คล้ายกันกับสตริงเช่นกันWHERE col BETWEEN 'a' AND 'z'จะไม่รวมแถว z ส่วนใหญ่
Martin Smith

8
ประเด็นนี้ถูกต้องแน่นอน แต่ไม่ควรแปลกใจถ้าคุณทำงานกับชุดข้อมูล มันคล้ายกับการชี้ให้เห็นBETWEEN 5 AND 10ว่าไม่ได้รวม10.2...
Andrzej Doyle

4
CASTไอเอ็นจีdatetimeเป็นจะทำงาน:DATE CAST(DATE_TIME_COL AS DATE) BETWEEN '01/01/2009' AND '01/31/2009'
craig

2
@craig นั่นเป็นความจริงตราบใดที่คุณกำลังใช้ SQL 2008 หรือสูงกว่าซึ่งก็คือเมื่อมีการเปิดตัวประเภทข้อมูลวันที่ นอกจากนี้ไวยากรณ์นั้นจะแปลงค่าดังกล่าวสำหรับทุกแถวดังนั้นจะไม่สามารถใช้ดัชนีใด ๆ ในฟิลด์นั้น (หากเป็นข้อกังวล)
BradC

It is entirely possible to have records created within that last second of the day, with a datetime as late as 01/01/2009 23:59:59.997<- คุณแทบจะใช้ไม่ได้เลยAND '01/31/2009 23:59:59.99999999'หรือจะต้องใช้หลาย ๆ อย่าง 9 อัน
wal

16

ตัวอย่างโลกแห่งความจริงจาก SQL Server 2008

แหล่งข้อมูล:

ID    Start
1     2010-04-30 00:00:01.000
2     2010-04-02 00:00:00.000
3     2010-05-01 00:00:00.000
4     2010-07-31 00:00:00.000

ค้นหา:

SELECT
    *
FROM
    tbl
WHERE
    Start BETWEEN '2010-04-01 00:00:00' AND '2010-05-01 00:00:00'

ผล:

ID    Start
1     2010-04-30 00:00:01.000
2     2010-04-02 00:00:00.000

ข้อความแสดงแทน


ฉันไม่ได้รับคำตอบจากคุณ บางทีผู้ให้บริการอินเทอร์เน็ตของฉันอาจซ่อนภาพหน้าจอของคุณหากคุณโพสต์ไว้
anar khalilov

2
เหตุใดแถวจึงID = 3ถูกแยกออก Startค่าของมันเท่ากับค่าขอบเขตBETWEENบนและBETWEENเป็นช่วงที่ครอบคลุมไม่ใช่ช่วงขอบเขตพิเศษ
ได

คำตอบที่ดีกว่าพร้อมผลลัพธ์
Sam

13

หากคุณกดปุ่มนี้และไม่ต้องการลองและจัดการกับการเพิ่มรหัสในหนึ่งวันให้ DB ทำเช่นนั้น ..

myDate >= '20090101 00:00:00' AND myDate < DATEADD(day,1,'20090101 00:00:00')

หากคุณรวมเวลาส่วน: ตรวจสอบให้แน่ใจว่ามันอ้างอิงเที่ยงคืน มิฉะนั้นคุณสามารถละเว้นเวลา:

myDate >= '20090101' AND myDate < DATEADD(day,1,'20090101')

และไม่ต้องกังวลกับมัน


12

ระหว่าง (Transact-SQL)

ระบุช่วง ( n ) ( รวม ) เพื่อทดสอบ

test_expression [ NOT ] BETWEEN begin_expression AND end_expression

ข้อโต้แย้ง

test_expression

เป็นนิพจน์ที่จะทดสอบในช่วงที่กำหนดโดย start_expression และ end_expression test_expression ต้องเป็นชนิดข้อมูลเดียวกันกับทั้ง start_expression และ end_expression

NOT

ระบุว่าผลลัพธ์ของเพรดิเคตจะถูกทำให้เป็นโมฆะ

begin_expression

เป็นการแสดงออกที่ถูกต้องใด ๆ start_expression ต้องเป็นชนิดข้อมูลเดียวกันกับทั้ง test_expression และ end_expression

end_expression

เป็นการแสดงออกที่ถูกต้องใด ๆ end_expression ต้องเป็นชนิดข้อมูลเดียวกันกับทั้ง test_expression และ start_expression

AND

ทำหน้าที่เป็นตัวยึดตำแหน่งที่ระบุ test_expression ควรอยู่ในช่วงที่ระบุโดย start_expression และ end_expression

หมายเหตุ

ในการระบุช่วงพิเศษให้ใช้ค่ามากกว่า (>) และน้อยกว่าตัวดำเนินการ (<) หากอินพุตใด ๆ ไปยังระหว่าง BETWEEN หรือ NOT BETWEEN เป็น NULL ผลที่ได้คือไม่รู้จัก

ค่าผลลัพธ์

ระหว่างผลตอบแทน TRUE ถ้าค่าของ test_expression มากกว่าหรือเท่ากับค่าของ start_expression และน้อยกว่าหรือเท่ากับมูลค่าของ end_expression

NOT BETWEEN ส่งคืน TRUE หากค่าของ test_expression น้อยกว่าค่าของ start_expression หรือมากกว่าค่า end_expression


3

หากชนิดข้อมูลคอลัมน์เป็นวันที่และเวลาคุณสามารถทำสิ่งต่อไปนี้เพื่อกำจัดเวลาจากวันที่และเวลาและเปรียบเทียบระหว่างช่วงวันที่เท่านั้น

where cast(getdate() as date) between cast(loginTime as date) and cast(logoutTime as date)

วิธีนี้ใช้งานได้ดีกว่าการเพิ่ม +1 ในวันที่สิ้นสุด ฉันเห็นด้วยกับ Andrew Morton - หากไม่สามารถทำได้ก็อาจปรับปรุงประสิทธิภาพในการเปลี่ยนประเภทข้อมูลคอลัมน์หรือเพิ่มคอลัมน์ที่สองด้วยวันที่คำนวณล่วงหน้าเท่านั้น
Arno Peters

0

มันมีขอบเขต

declare @startDate date = cast('15-NOV-2016' as date) 
declare @endDate date = cast('30-NOV-2016' as date)
create table #test (c1 date)
insert into #test values(cast('15-NOV-2016' as date))
insert into #test values(cast('20-NOV-2016' as date))
insert into #test values(cast('30-NOV-2016' as date))
select * from #test where c1 between @startDate and @endDate
drop table #test
RESULT    c1
2016-11-15
2016-11-20
2016-11-30


declare @r1 int  = 10
declare @r2 int  = 15
create table #test1 (c1 int)
insert into #test1 values(10)
insert into #test1 values(15)
insert into #test1 values(11)
select * from #test1 where c1 between @r1 and @r2
drop table #test1
RESULT c1
10
11
15

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