SQL: ARASINDA - <= ve> =


111

SQL Server 2000 ve 2005'te:

  • bu iki WHEREcümle arasındaki fark nedir?
  • Hangi senaryolarda hangisini kullanmalıyım?

Sorgu 1:

SELECT EventId, EventName
FROM EventMaster
WHERE EventDate BETWEEN '10/15/2009' AND '10/18/2009'

Sorgu 2:

SELECT EventId, EventName
FROM EventMaster
WHERE EventDate >='10/15/2009'
  AND EventDate <='10/18/2009'

(Düzenleme: ikinci Eventdate başlangıçta eksikti, bu nedenle sorgu sözdizimsel olarak yanlıştı)



6
aslında değil, tarih saatinin işlenmesi biraz farklıdır, artı bu SQL server 2008 içindi ve Shyju'nun cevabın önceki sürümler için aynı olacağını sormadan emin olmasının bir yolu yok.
Irfy

Yanıtlar:


119

Aynıdırlar: BETWEENsorudaki daha uzun sözdiziminin kısaltmasıdır.

BETWEENÇalışmayan alternatif bir uzun sözdizimi kullanın, ör.

Select EventId,EventName from EventMaster
where EventDate >= '10/15/2009' and EventDate < '10/18/2009'

( İkinci koşul <yerine not edin <=.)


19
Belki ikinci koşulun '<' olduğunu vurgulamalısınız. Farkı görmem biraz zaman aldı.
zendar

21
DATE veri türü ile uğraşmıyorsanız veya başka bir şekilde datetime değerlerinin hiçbir zaman bir zaman bileşenine sahip olmayacağını garanti etmedikçe BETWEEN'i asla kullanmamanızı şiddetle tavsiye ederim. Bu konuda tutarlı olmak, yanlışlıkla> = ve <yerine BETWEEN'i kullanma olasılığınızı azaltır ve sorguda istemediğiniz bazı verileri alırsınız veya ek bir gün aldığınızı düşünürsünüz. değilken veriler ...
Aaron Bertrand

1
BETWEEN koşullulara dönüştürüldüğünde ikinci bir derleyici adımı olur mu? Bunun biraz bilgiçlikçi olduğunu anlıyorum, ancak ek bir ek yük olur mu?
James Scott

1
@xmashallax onlar oldukları için mi? Nasıl değiller?
Tony Andrews

2
Garip ... Sanırım soru, cevabın yazılması, yorumlar ve
kodumun

37

Onlar aynı.

Dikkat edilmesi gereken bir nokta, bunu bir DATETIME için kullanıyorsanız, bitiş tarihi için maç günün başlangıcı olacaktır:

<= 20/10/2009

şununla aynı değil:

<= 20/10/2009 23:59:59

(Bu olur karşılaştırılamaz <= 20/10/2009 00:00:00.000)


Günü yakalamak için '2009-10-20' ve '2009-10-21' arasında kullanabilirsiniz
David Andrei Ned

4
@DavidAndreiNed bu da '2009-10-21 00: 00: 00.000' ile eşleşir - muhtemelen istediğiniz gibi değil.
Hans Ke st ing

2
'2009-10-20 00:00:00' VE '2009-10-20 23:59:59' ARASINDA veya> = '2009-10-20 00:00:00' VE alan <= '2009-10-20 23:59:59' kesinlikle kesin.
2019

@geilt Örnekleriniz günün son saniyesinde meydana gelen her şeyi gözden kaçıracaktır ... yani: ertesi gün 23:59:59 ile 00:00:00 arasında.
Seth Flowers

00:00:00 ertesi günün başlangıcıdır ve neden> = ve <= kullandım ve> veya <. Ama mikrosaniyeleri kastettiyseniz ve bunları kaydediyorsanız, son ve son mikrosaniyeyi de koymak istersiniz.
2019 7

14

BETWEENOkuması ve bakımı kolay olmasına rağmen , kapalı bir aralık olduğundan ve daha önce de belirtildiği gibi bu, zaman bileşenleri olmasa bile tarihlerle ilgili bir sorun olabileceğinden kullanımını nadiren tavsiye ederim.

Örneğin, aylık verilerle uğraşırken tarihleri ​​karşılaştırmak genellikle yaygındır BETWEEN first AND last, ancak pratikte bunu yazmak genellikle daha kolaydır dt >= first AND dt < next-first(bu, zaman bölümü sorununu da çözer) - çünkü belirleme lastgenellikle belirlemekten bir adım daha uzundur next-first(bir günü çıkararak) .

Ek olarak, başka bir sorun da, alt ve üst sınırların doğru sırada (yani BETWEEN low AND high) belirtilmesi gerektiğidir .


4

Tipik olarak hiçbir fark yoktur - BETWEENanahtar kelime tüm RDBMS platformlarında desteklenmez, ancak destekleniyorsa iki sorgu aynı olmalıdır.

Özdeş olduklarından, hız veya başka bir şey açısından gerçekten bir ayrım yoktur - size daha doğal görüneni kullanın.


4

@Marc_s, @Cloud, et al. kapalı bir aralık için temelde aynıdırlar.

Ancak herhangi bir kesirli bir zaman değerleri (daha yüksek veya-eşit ve kapalı bir dizi soruna neden olabilir az ya da eşit (daha-eşit veya ve yarı açık bir dizi karşıt olarak) daha az daha ) bir uç değer ile sonra mümkün olan son an.

Bu nedenle, sorgunun şu şekilde yeniden yazılması gerektiğini önlemek için:

SELECT EventId, EventName
  FROM EventMaster
 WHERE (EventDate >= '2009-10-15' AND
        EventDate <  '2009-10-19')    /* <<<== 19th, not 18th */

Yana BETWEENyarı açık aralıkları için çalışmıyor Hep herhangi bir tarih / zaman sorgudan de sert bir görünüm alır kullanımlar o, onun muhtemelen bir hata beri.


4

Küçük bir tercihim var BETWEENçünkü okuyucuya bir aralık için bir alanı kontrol ettiğinizi anında netleştiriyor . Tablonuzda benzer alan adları varsa bu özellikle doğrudur.

, Derseniz, bizim masa a hem sahiptir transactiondateve bir transitiondateben okursanız,

transactiondate between ...

Testin her iki ucunun da bu alana karşı olduğunu hemen biliyorum.

Okursam

transactiondate>='2009-04-17' and transactiondate<='2009-04-22'

İki alanın aynı olduğundan emin olmak için biraz daha zaman ayırmam gerekiyor.

Ayrıca, bir sorgu zamanla düzenlendikçe, dikkatsiz bir programcı iki alanı ayırabilir. Şöyle bir şey söyleyen çok sayıda sorgu gördüm

where transactiondate>='2009-04-17'
  and salestype='A'
  and customernumber=customer.idnumber
  and transactiondate<='2009-04-22'

Bunu bir ile denerlerse BETWEEN, elbette, bir sözdizimi hatası olur ve derhal giderilir.


3

Bence tek fark, her sorguda sözdizimsel şeker miktarı. BETWEEN, ikinci sorgu ile tamamen aynı şeyi söylemenin basit bir yoludur.

Farkında olmadığım bazı RDBMS'ye özgü farklılıklar olabilir, ancak gerçekten öyle düşünmüyorum.


2

Mantıksal olarak hiçbir fark yoktur. Performans açısından -tip olarak, çoğu DBMS'de- hiçbir fark yoktur.



1

Sorumluluk Reddi: Aşağıdaki her şey sadece anekdottur ve doğrudan kişisel deneyimlerimden alınmıştır. Ampirik açıdan daha titiz bir analiz yürütmek için kendini iyi hisseden herhangi biri bunu gerçekleştirebilir ve eğer ben olursam oyu reddedebilir. Ayrıca SQL'in bildirimsel bir dil olduğunu ve kodunuzu yazarken nasıl işlendiğini göz önünde bulundurmanız gerekmediğinin farkındayım, ancak zamanıma değer verdiğim için yapıyorum.

Mantıksal olarak eşdeğer sonsuz sayıda ifade vardır, ancak üç (ish) ele alacağım.

Durum 1: Standart sırayla iki Karşılaştırma (Değerlendirme sırası sabit)

A> = MinBound VE A <= MaxBound

Durum 2: Sözdizimsel şeker (Değerlendirme sırası yazar tarafından seçilmemiştir)

MinBound VE MaxBound ARASINDA

Durum 3: Eğitimli bir sırayla iki Karşılaştırma (Yazma zamanında seçilen değerlendirme sırası)

A> = MinBound VE A <= MaxBound

Veya

A <= MaxBound VE A> = MinBound

Tecrübelerime göre, Durum 1 ve Durum 2, veri kümelerinden habersiz oldukları için performans açısından tutarlı veya dikkate değer farklılıklar göstermemektedir.

Ancak, Durum 3, yürütme sürelerini büyük ölçüde iyileştirebilir. Spesifik olarak, büyük bir veri kümesiyle çalışıyorsanız ve A'nın MaxBound'dan daha büyük veya MinBound'dan daha düşük olup olmadığı konusunda biraz sezgisel bilgiye sahipseniz, Durum 3'ü kullanarak ve karşılaştırmaları sıralayarak yürütme sürelerini önemli ölçüde iyileştirebilirsiniz. buna göre.

Sahip olduğum bir kullanım örneği, belirli bir aralıktaki kayıtlar için dizine eklenmemiş tarihler içeren büyük bir tarihsel veri kümesini sorgulamaktır. Sorguyu yazarken, belirtilen aralıktan ÖNCE veya belirtilen aralıktan SONRA daha fazla veri olup olmadığı konusunda iyi bir fikre sahip olacağım ve karşılaştırmalarımı buna göre sıralayabilirim. Veri kümesinin boyutuna, sorgunun karmaşıklığına ve ilk karşılaştırmada filtrelenen kayıtların miktarına bağlı olarak yürütme süreleri yarı yarıya azaldı.


Um, ne? Durum 3, Durum 1 ve Durum 2 ile aynı mantığı paylaşmaz. AHer iki sınırdan da daha büyük olup olmadığını görmek istiyorsanız , o zaman sadece Adaha büyük olup olmadığını kontrol edin MaxBound. Gönderinizin biraz ayarlanması gerekiyor.
mickmackusa

Eşitlik operatörlerinde bir yazım hatası yapmışım gibi görünüyor. İyi yakalama.
LanchPad

0

Bu senaryoda col BETWEEN ... AND ...ve col <= ... and col >= ...eşdeğerdir.


SQL Standard ayrıca T461 Simetrik BETWEEN yüklemini de tanımlar :

 <between predicate part 2> ::=
 [ NOT ] BETWEEN [ ASYMMETRIC | SYMMETRIC ]
 <row value predicand> AND <row value predicand>

Transact-SQL bu özelliği desteklemez.

BETWEENdeğerlerin sıralanmasını gerektirir. Örneğin:

SELECT 1 WHERE 3 BETWEEN 10 AND 1
-- no rows

<=>

SELECT 1 WHERE 3 >= 10 AND 3 <= 1
-- no rows

Diğer yandan:

SELECT 1 WHERE 3 BETWEEN SYMMETRIC 1 AND 10;
-- 1

SELECT 1 WHERE 3 BETWEEN SYMMETRIC 10 AND 1
-- 1

Tam olarak normal gibi çalışır, BETWEENancak karşılaştırma değerlerini sıraladıktan sonra.

db <> fiddle demosu

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.