MS SQL Server'ın “arasında” aralık sınırları var mı?


234

Örneğin

SELECT foo
FROM bar
WHERE foo BETWEEN 5 AND 10

5 ve 10'u seçin veya bunlar aralıktan çıkarıldı mı?

Yanıtlar:


258

BETWEEN operatörü kapsayıcıdır.

Çevrimiçi Kitaplardan:

Test_expression değeri begin_expression değerinden büyük veya ona eşitse ve end_expression değerinden küçük veya ona eşitse BETWEEN, TRUE değerini döndürür.

DateTime Uyarısı

Not: DateTimes ile dikkatli olmalısınız; yalnızca bir tarih verilirse, değer o gün gece yarısından itibaren alınır; bitiş tarihinizde eksik süreleri önlemek veya ertesi günün verilerinin alınmasını birden fazla aralıkta gece yarısında tekrarlamak için bitiş tarihiniz, tarihinden sonraki günün gece yarısından 3 milisaniye önce olmalıdır. 3 milisaniye çünkü bundan daha az ve değer ertesi gün gece yarısına yuvarlanacak.

örneğin, Haziran 2016'daki tüm değerleri elde etmek için şunları çalıştırmanız gerekir:

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

yani

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

datetime2 ve datetimeoffset

Bir tarihten 3 ms çıkarılması, 3 ms penceresindeki eksik satırlara karşı savunmasız kalmanıza neden olur. Doğru çözüm de en basit çözümdür:

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

11
DateTimes'ı iki tarih arasında filtrelemek için BETWEEN'i kullanırken DateTime'ı bir Tarihe de aktarabilirsiniz, örneğin: burada CONVERT (DATE, MyDate) '2017-09-01' ve '2017-09-30' ARASINDA DateTime öğesi ilgisiz
Pete

1
Bir tarihten 3 msn çıkarmaya çalışmamaya dikkat edin; bu 3 ms'den öğeleri özleyeceksiniz. Ve ayrıca istemiyoruz CONVERTa datetime a tarihinden bu yararsız endeksler hale getirecek şekilde,. Standardı kullanın WHERE OrderDate >= '20160601' AND OrderDate < '20160701'. Ayrıca, yerel ayara bağlı yyyymmddolarak kullandığınızdan yyyy-mm-ddve sunucunuzun mdy, dmy, ymd, ydm, myd, and dymayarına bağlı olarak yanlış yorumlanacağından emin olun .
Ian Boyd

254

Evet, ancak tarihler arasında kullanırken dikkatli olun.

BETWEEN '20090101' AND '20090131'

gerçekten sabah 12 olarak yorumlanır veya

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

31 Ocak gününde meydana gelen her şeyi kaçıracaksınız. Bu durumda, kullanmanız gerekecek:

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

veya

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

GÜNCELLEME : Günün son saniyesinde, tarih ve saat kadar geç kayıtların oluşturulması tamamen mümkündür 20090101 23:59:59.997!!

Bu nedenle BETWEEN (firstday) AND (lastday 23:59:59)yaklaşım önerilmemektedir.

Kullanım myDate >= (firstday) AND myDate < (Lastday+1)yerine yaklaşım.

Burada bu konuda iyi bir makale .


1
Dizelerle ilgili benzer sorunlar, WHERE col BETWEEN 'a' AND 'z'örneğin z satırlarının çoğunu hariç tutacaktır.
Martin Smith

8
Bu nokta elbette haklıdır; ama eğer günlerle çalışıyorsanız şaşırtıcı olmamalı. Aşağıdakileri BETWEEN 5 AND 10içermediğine işaret etmek benzer 10.2...
Andrzej Doyle

4
CASTing datetimebir şekilde DATEçalışacak: CAST(DATE_TIME_COL AS DATE) BETWEEN '01/01/2009' AND '01/31/2009'.
craig

2
@craig, SQL 2008 veya daha üst bir sürüm kullandığınız sürece, bu tarih veri türünün kullanıma sunulduğu zamandır. Ayrıca, bu sözdizimi her bir satır için bu değeri dönüştürecektir, bu nedenle o alanda herhangi bir dizin kullanamazsınız (bu bir endişe kaynağıysa).
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<- daha sonra kullanamaz mıydınız AND '01/31/2009 23:59:59.99999999'veya çok sayıda 9 gereklidir
wal

16

SQL Server 2008'den gerçek dünya örneği.

Kaynak veriler:

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

Sorgu:

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

Sonuçlar:

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

alternatif metin


Dürüst olmak gerekirse cevabını alamadım. Belki de yayınladıysanız internet sağlayıcım ekran görüntünüzü gizlemiştir.
anar khalilov

2
Neden satır ID = 3hariç tutulur? Onun Startdeğeri eşittir BETWEENüst sınır değeri ve BETWEENkapsayıcı aralık değil, özel bir üst sınırlı aralığıdır.
Dai

Sonuçlarla daha iyi cevap.
Sam

13

Eğer buna çarptıysanız ve gerçekten bir gün kod eklemeyi denemek ve işlemek istemiyorsanız, DB'nin yapmasına izin verin ..

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

Zaman bölümünü eklerseniz: gece yarısı referans aldığından emin olun. Aksi takdirde zamanı atlayabilirsiniz:

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

ve endişelenmeyin.


12

ARASINDA (Transact-sql)

Test edilecek bir ( n ) ( dahil ) aralığı belirtir .

test_expression [ NOT ] BETWEEN begin_expression AND end_expression

Argümanlar

test_expression

Test edilecek ifade, begin_expression ve end_expression tarafından tanımlanan aralıktadır. test_expression, hem begin_expression hem de end_expression ile aynı veri türünde olmalıdır.

NOT

Yüklemenin sonucunun reddedileceğini belirtir.

begin_expression

Geçerli herhangi bir ifadedir. begin_expression, hem test_expression hem de end_expression ile aynı veri türünde olmalıdır.

end_expression

Geçerli herhangi bir ifadedir. end_expression, hem test_expression hem de begin_expression ile aynı veri türünde olmalıdır.

AND

Test_ifadesi'ni belirten bir yer tutucu gibi davranıyor, başlangıç_ifadesi ve bitiş_ifadesi ile belirtilen aralık içinde olmalıdır.

Uyarılar

Özel bir aralık belirtmek için, büyüktür (>) ve küçüktür (<) kullanın. Yüklem arasında BETWEEN veya NOT DEĞİLDİR herhangi bir girdi NULL ise, sonuç UNKNOWN olur.

Sonuç Değeri

Test_expression değeri begin_expression değerinden büyük veya ona eşitse ve end_expression değerinden küçük veya ona eşitse BETWEEN, TRUE değerini döndürür.

Test_expression değeri begin_expression değerinden küçük veya end_expression değerinden büyükse BETWEEN, TRUE değerini döndürmez.


3

Sütun veri türü datetime ise, datetime zamanını ortadan kaldırmak ve yalnızca tarih aralığı arasında karşılaştırma yapmak için bunu yapabilirsiniz.

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

Bu, bitiş tarihine +1 eklemekten daha iyi sonuç verir. Andrew Morton'a katılıyorum - eğer anlaşılmaz değilse, sütun veri türünü değiştirmek veya yalnızca önceden hesaplanmış tarihlere sahip ikinci bir sütun eklemek için performansı artırabilir.
Arno Peters

0

Sınırları içerir.

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

-3

Bunu hep kullandım:

StartDate AND (endDate + 1) ARASINDAKİ myDate

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.