Neden SQL’in BETWEEN’i yarı açık değil?


45

Yarı açık (veya Yarı Açık Yarı Kapalı , yarı Sınırlı () aralıkları [a,b), xaralık IFF ait a <= x < bpek çok kullanışlı özelliklere sahip gibi), programlama oldukça yaygındır.

SQL'in neden BETWEENkapalı bir aralık ( [a,b]) kullandığını açıklayan bir gerekçe var mı? Bu esp. tarihler için uygunsuz. Neden böyle BETWEENdavranıyorsun?


Merak ediyorum, hangi uygun özelliklere sahipler?
phant0m

2
Kapsayıcı olmasaydı, A ve D aralığındaki tüm soyadları kolayca nasıl sorgulayabilirdiniz? veya W'den Z'ye isimleri? 1 ile 10 arasındaki rakamlar için 0 <n <11 arayabilirsiniz, ancak karakterler için ASCII numaralarını kullanmak zorunda mıydınız? veya unicode sayıları? Ayrıca, dizinler sizi kolayca verilerinizin başlangıcına götürebilir.
jqa,

2
Hayal kırıklığınızı anlıyorum, (StartDate> = '2010-01-01' ve StartDate <'2011-01-01'), eşdeğerleri arasında kullanmak için güzel çalışır, '2010-01-01' ve ' 2010-12-31 23:59:59 '), hem hantalın hem de kişinin Aralık'ta kaç gün olduğunu bilmesi gerekiyor.
Todd

1
@ phant0m [a, b) U [c, d) == [a, d). [a: int, b: int) tam olarak ba elementleri içerir. Todd'un yorumu özellikle tarihler için nasıl iyi çalıştıklarını gösteriyor (ki bu onları çok özledim). Temel olarak, kodlama yaparken, semiopen aralıkları daha basit, kullanımı daha kolay ve sağlam olma eğilimindedir.
alex

En iyi cevap, SQL için BETWEEN'i ilk belirten kişilerden objektif karar belgelerine atıfta bulunmalı ve böylece seçilen öznel cevaptan ziyade Neden'e cevap vermelidir.
Todd

Yanıtlar:


48

Kapsayıcı BETWEENolduğunu düşündüğümden daha sezgisel (ve görünüşe göre SQL tasarımcıları da) yarı açık bir aralıktan daha fazla. Örneğin, "1 ile 10 arasında bir sayı seç" dersem, çoğu insan 1 ve 10 sayılarını içerecektir. Açık uçlu aralık aslında geliştiriciler için kafa karıştırıcıdır çünkü asimetriktir. SQL bazen basit sorguları yapmak olmayan programcılar tarafından kullanılır ve yarı açık semantik olurdu çok onlar için kafa karıştırıcı fazlası.


9
Örneğin, ondalık sayılar ve diğer sınırlandırılmış büyüklükler için (tarihler gibi) tam sayılara odaklanır, arasındaki terim belirsizdir. 2012 ve 2013 yılları arasında X yaptınız mı dersem, 2013'ü (veya özellikle 2013-01-01 gününü) dahil etmiyorum
Todd

4
@Todd Bu terimlerin herhangi bir kullanımı belirsizdir. Bu nedenle matematikçiler, bilim insanları ve anlayışlı programcıların niyetlerini "yarı açık" gibi bir şey olarak belgeliyorlar. Bence Oleski'nin cevabı, SQL'in aslında programcılar yerine son kullanıcılar için tasarlandığı (gerçekten!). Görünüşe göre, SQL tasarımcıları, o izleyici için en iyi düşündükleri bir tanımda bir bıçak aldı. Ancak, Sorunun yazarlarının önerdiği gibi yarı açık, zaman aralığı gibi aralıklar ile çalışmak için hemen hemen her zaman daha iyidir.
Basil Bourque

“BEDWEEN'in daha sezgisel olduğunu düşünüyorum” özneldir. "SQL bazen programcılar tarafından basit sorgular yapmak için kullanılır" - Programcılar dışındaki kişilerin de aynı şekilde işaretlemeleri gerekir.
Todd


Sorusu da sık sık "Bir sayı tut sorulan dan 1'e kadar (sadece bariz belirsizlik önlemek için) 10". Yan not olarak. "1 ile 10 arasında bir sayı seç" diyorsunuz; çoğu insan muhtemelen 1 veya 10'u seçmezdi. Bunun bir psikoloji sorunu olduğunu kabul ediyorum . :) İnsanlar hala 1 ve 10'u geçerli seçenekler olarak kabul ederler (anlamsal olarak yanlış olmasına rağmen); ancak bu, 1 ve 10'un geçerli olduğunu varsaydığı bağlamsal yorumlamanın bir sonucudur . “13 ile 24 arasında” demeniz ve 13 ile 24'ün dahil olup olmadığı sorulma ihtimaliniz daha yüksek.
Disillusioned

25

SORU: SQL'in ARASINDAKİ ARASINDAKİ NEDİR?

CEVAP: Çünkü SQL dili tasarımcıları, zayıf bir tasarım kararı verdiler, çünkü geliştiricilerin BETWEEN'in 4 türevinden hangisini (kapalı, yarı açık-sol, yarı-açık-açık veya açık) belirtmesine izin verecek sözdizimi sunmadılar. ) tercih ederlerdi.

ÖNERİ: SQL standardı değiştirilinceye kadar / sürece, tarih / saatler için BETWEEN kullanmayın. Bunun yerine, BETWEEN ürün yelpazenizin başlangıç ​​ve bitiş sınırlarında bağımsız koşullar olarak DATE aralığı karşılaştırmalarını kodlama alışkanlığını edinin. Bu biraz ayrıntılı, ancak sezgisel (dolayısıyla daha az hatalu olması muhtemel olan) yazma koşullarını bırakacak ve en uygun yürütme planlarının belirlenmesini ve endekslerin kullanılmasını sağlayan veritabanı optimizerlerine açıklık getirecektir.

Örneğin, sorgunuz bir giriş günü şartnamesini kabul ediyorsa ve o tarihe düşen tüm kayıtları iade etmeli, aşağıdaki gibi kodlarsınız:

  • WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1

BETWEEN kullanarak mantığı yazmaya çalışmak performans sorunları ve / veya buggy kodu ile tehlikeye girer. Üç yaygın yanlış adım:

1) WHERE DATE_FIELD BETWEEN :dt AND :dt+1

Bu neredeyse kesin bir hatadır - kullanıcı sadece belirli bir tarih için kayıtları görmeyi bekler, ancak bir gün ertesi gün saat 12: 00'den itibaren kayıtları içeren bir raporla sonuçlanır.

2) WHERE TRUNC(DATE_FIELD) = :dt

Doğru cevap verir, ancak işlevi DATE_FIELD uygulamasına uygulamak çoğu indeksleme / istatistiği işe yaramaz hale getirir (bazen DBA'lar tarih alanlarına işlev tabanlı dizinler ekleyerek yardım etmeye çalışacaktır - yine de çalışma saatlerini ve disk alanını yakıp IUD'ye ek yük masadaki işlemler)

3) WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60

Oracle gurusu extraordinaire Tom Kyte, bu zariften daha küçük (IMO) çözümü önerir. "1-1 / 24/06/60" 'ı bulmak için bütün gününü harcayana kadar ya da eksik sonuçlar veren bir sorguda ... ya da yanlışlıkla bir TIMESTAMP alanında kullanana kadar harika çalışıyor. Ayrıca, biraz tescilli; Oracle'ın DATE veri türüyle uyumludur (ikinciyi takip eder), ancak farklı veritabanı ürünlerinin DATE / TIME hassasiyetine göre ayarlanması gerekir.

ÇÖZÜM: KAPALI / İÇERİK varsayılanına alternatiflerin belirtilmesini desteklemek için BETWEEN sözdizimini değiştirerek SQL dil özelliklerini geliştirmek için ANSI SQL komitesine dilekçe verin. Böyle bir şey hile yapar:

ifade1 ARASINDAKİ ifade2 [ DAHİL [USIVE] | EXCL [USIVE]] VE expr3 [ DAHİL [USIVE] | EXCL [KULLANIM]

Bunu ifade etmenin ne kadar kolay olduğunu düşünün WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE(veya sadece WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL)

Belki ANSI SQL: 2015?


Bu cevap adalet tavsiyesidir.
Basil Bourque

@KevinKirkPatrick - Harika cevap! Ayrıca, karar belgelerini orijinal Neden'in nesnel kanıtı olarak bulmaya çalışmanızı da öneririm.
Todd

3
Şahsen ben exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3operatörün aralarında kalmasını sağladığın için hoşuma gidiyor , bu yüzden menzilli bir tahmin olduğunu biliyorsun ve eşitsizlik öngörüsü bunun yarı açık olmasını sağlıyor.
Sentinel

@Sentinel, Nice! Kendimi vaktinden önce bir dönüşüm ilan edemeyeceğim, ancak kesinlikle bir sonraki kod tarih aralığı koşullarında aklımda olacağım. İlk bakışta, exp1> = exp2 AND exp1 <exp3; den daha büyük bir dil çekiciliği vardır; ve açıkça BETWEEN ile eşit derecede iyi çözer. Herhangi bir optimize ediciden biri diğerine göre bir varyasyondan daha iyi bir "anlayış" gösterirse ilgilenirim; şüphesiz, sizinkiler de bu konuda daha iyi sonuçlar verebilecek gibi görünüyor (açıkçası, onlara farklı şekilde davranan optimizerde oldukça hayal kırıklığına uğradım)
KevinKirkpatrick 09:15

@KevinKirkpatrick Farkında olup olmadıklarını belirlemek için onları hiçbir zaman profillendirmedim, ve ben de olsa hayal kırıklığına uğrayacağım.
Sentinel

8

Hem dahil ( a <= x <= b) hem de exclusive ( a < x < b) eşit derecede yaygındır, bu yüzden standartları yaparken sadece birini seçmek zorunda kaldılar. Ortak İngilizce'de "arasında" genellikle kapsayıcıdır ve bir SQL deyiminin İngilizce bir cümleyi benzer şekilde okuması amaçlanmıştır, bu nedenle kapsayıcı bir seçimdir.


4
Aslında İngilizce'de kullanım, Half-Open'ı bıraktığınız zaman daha da karışık. Öğlen ve öğlen 13: 00 arası olduğunu söylediğimizde, yarının ilk anı da dahil olmak üzere ancak 13: 00: 00.000'de sınıfa / işe geri dönmeniz beklenirken yarı açık olduğunu kastediyoruz . saat başı bir. a <= x < bYarı Açık.
Basil Bourque

1
@BasilBourque: Bu sonsuz hassasiyete bağlı olabilir - örneğin öğle yemeği öğlen ve 12: 59: 99.9999999999999 .... arasında öğleden sonra ....
Brendan

@Brendan Evet, sen benim fikrimi söylüyorsun. Sonsuz (veya belirsiz) hassasiyet, bir zaman dilimini tanımlamak için yarı açık yaklaşım kullanılarak ele alınan problemlerden biridir. Buradaki nokta, İngilizce konuşmamızda sezgisel olarak açık ve kapalı (bu yanıtta belirtildiği gibi) yanı sıra fazla düşünmeden yarı açık aralıkları ele almamızdır. Her yaklaşım bir amaca hizmet eder. BETWEEN'in SQL tanımının optimalin altında olmasının nedeni budur. İdeal olarak, SQL KevinKirkpatrick'in önerisini izleyecektir .
Basil Bourque,

2
SQL'in İngilizce olduğu varsayılır ve kapsayıcı ve ayrıcalıklı olsa da aynı derecede yaygın olabilir, ancak analistler ve programcılar için bir sorgu dilidir. Bir programcı olarak bence yanlış tanımlanmış, ancak bu gerçekten önemli değil, yine de "BETWEEN" kullanmaktan kaçınıyorum. Önemli bir şey değil.
Todd

5

Operatör çağrılmadı ∩[a,b), çağrıldı BETWEEN, bu nedenle anlambilimlerinin "yarı açık aralıklı" olan "matematiksel yüklemin ifadeleri arasında" olduğu anlamına gelen İngilizce cümlenin ifadesi olması daha uygun .


Bir Integer setler için sadece İngilizce uygulamaları değil, tüm uygulamaları göz önünde bulundurmanız gerekir. "1 ile 10 arasında", "öğlen ile 13 arasında", "1,0 ile 5,0 arasında" (gram). "5.50 ile 10.30 arasında" (dolar). Sürekli miktarların mantıklı (İngilizce olarak) özel olduğu varsayılır.
Todd

1
Sorun, BETWEENoperatörün , "aralarında" ifadesinin İngilizce anlamını kullanmamasıdır. İngilizce "arasında" şeyleri ayıran zaman, boşluk veya aralıktır ( münhasır değildir ). Bir gol atmaya çalışırsanız, topun atmak için yazılar arasında gitmesi gerekir. Eğer yazıyı geçemezseniz yazıyı vurursanız - sizin için puan yok.
Hayal kırıklığına uğramış

1
@CraigYoung kabul edilen cevabın da önerdiği gibi (ve katılıyorum), "Eğer" 1 ile 10 arasında bir sayı seçsem "dediğimde, çoğu insan 1 ile 10 arasındaki rakamları [muhtemel cevaplar arasında] içerecektir". Bir de mekansal etki Sana katılıyorum ama sayılar için Ben farklı olduğunu söyleyebilirim. İçin daha iyi İngiliz Dili ve Kullanımı burada olsa daha!
AakashM

@AakashM Amacım, programlama anlamını haklı çıkarmak için "arasında" kelimesinin sözlük tanımıyla yanlış olan İngilizce dili hakkında bir iddiada bulunduğunuzdur. "1 ile 10 arasında" tabirinin ortak bir anlayışı olduğu gerçeği, ondalık sayı sisteminde "1" ile "10" arasındaki konumlarla ilgili "arasında" ve daha fazlası anlamına gelmez. İnsan beyninin "otomatik düzeltmesi", "arasındaki" "bu durumda bitiş noktalarını dışlar, çünkü" 2'den 9'a "demek saçma görünüyor. Aynısını "13 ile 24 arasında" ile deneyin. Veya "0 ile 11 arasında" bile.
Hayal kırıklığına uğramış

Aramızda kalıyor, doğal dillerle ilgili kategorik iddialar genellikle güvensiz.
AakashM
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.