Perché SQL è TRA inclusivo piuttosto che semiaperto?


45

Gli intervalli semi-aperti (o semiaperti, semichiusi , semichiusi ) ( [a,b), dove xappartiene all'intervallo iff a <= x < b) sono piuttosto comuni nella programmazione, in quanto hanno molte proprietà convenienti.

Qualcuno può offrire una logica che spiega perché SQL BETWEENutilizza un intervallo chiuso ( [a,b])? Questo è esp. scomodo per le date. Perché dovresti BETWEENcomportarti così?


Sono curioso, quali proprietà convenienti hanno?
phant0m

2
se non fosse inclusivo, come si potrebbe facilmente cercare tutti i cognomi nell'intervallo da A a D? o dai nomi alla W? Per numeri tra 1 e 10 puoi cercare 0 <n <11, ma per i caratteri dovresti usare i numeri ASCII? o numeri unicode? Inoltre, gli indici possono facilmente portarti all'inizio dei tuoi dati.
jqa,

2
Capisco la tua frustrazione, (StartDate> = '2010-01-01' e StartDate <'2011-01-01'), funziona magnificamente, da usare Tra l'equivelent sarebbe (StartDate tra '2010-01-01' e ' 2010-12-31 23:59:59 '), entrambi ingombranti e bisogna sapere quanti giorni sono a dicembre.
Todd

1
@ phant0m [a, b) U [c, d) == [a, d). [a: int, b: int) contiene esattamente ba elementi. Il commento di Todd mostra come funzionano particolarmente bene per le date (che è dove mi mancano di più). Fondamentalmente, durante la codifica, gli intervalli di semiopen tendono ad essere più semplici, più facili da usare e robusti.
alex

La risposta migliore avrebbe dovuto fare riferimento alla documentazione di decisione obiettiva delle persone che per prima hanno specificato TRA per SQL, rispondendo in tal modo al Why, piuttosto che alla risposta soggettiva selezionata.
Todd,

Risposte:


48

Penso che l'inclusione BETWEENsia più intuitiva (e apparentemente, così come i progettisti SQL) di un intervallo semi-aperto. Ad esempio, se dico "Scegli un numero compreso tra 1 e 10", la maggior parte delle persone includerà i numeri 1 e 10. L'intervallo aperto è in realtà particolarmente confuso per i non sviluppatori perché è asimmetrico. SQL viene occasionalmente utilizzato da non programmatori per eseguire query semplici e la semantica semi-aperta sarebbe stata molto più confusa per loro.


9
Il tuo esempio si concentra su numeri interi, per numeri decimali e altre quantità delimitate (come le date), il termine tra è ambiguo. Se dico di aver fatto X tra il 2012 e il 2013, non includo il 2013 (o in particolare il giorno 01-01-2013)
Todd

4
@Todd Qualsiasi utilizzo di questi termini è ambiguo. Ecco perché matematici, scienziati e programmatori esperti documentano la loro intenzione come "semiaperta" o simile. Penso che il punto della risposta di Oleski sia che SQL era originariamente destinato agli utenti finali piuttosto che ai programmatori (davvero!). Apparentemente i progettisti di SQL hanno preso a pugni una definizione che pensavano fosse meglio per quel pubblico. Ma come suggeriscono gli autori della domanda, la mezza apertura è quasi sempre migliore per lavorare con intervalli come intervalli di tempo.
Basil Bourque,

"Penso che l'inclusione TRA sia più intuitiva" è soggettiva. "SQL viene occasionalmente utilizzato da non programmatori per eseguire query semplici" - I non programmatori dovrebbero ugualmente controllare le specifiche.
Todd,


Spesso viene anche posta la domanda "Scegli un numero da 1 a 10" (semplicemente per evitare l'ovvia ambiguità). Come nota a margine. Dici "scegli un numero tra 1 e 10"; la maggior parte delle persone probabilmente non sceglierebbe 1 o 10. Ammesso che sia più un problema di psicologia. :) Le persone accetterebbero comunque 1 e 10 come scelte valide (nonostante siano semanticamente errate); ma questo è il risultato dell'interpretazione contestuale supponendo che 1 e 10 siano validi. Se dovessi dire: "tra 13 e 24" e ti verrà più probabilmente chiesto se sono inclusi 13 e 24.
Disilluso il

26

DOMANDA: Perché è compreso SQL TRA?

RISPOSTA: poiché i progettisti del linguaggio SQL hanno preso una cattiva decisione di progettazione, in quanto non sono riusciti a fornire la sintassi che avrebbe consentito agli sviluppatori di specificare quale delle 4 varianti di BETWEEN (chiusa, semi-aperta-sinistra, semi-aperta-destra o aperta ) preferirebbero.

RACCOMANDAZIONE: A meno che / fino a quando non viene modificato lo standard SQL, non utilizzare TRA date / orari. Prendi invece l'abitudine di codificare i confronti dell'intervallo DATE come condizioni indipendenti sui limiti iniziale e finale dell'intervallo TRA. Questo è un po 'dettagliato, ma ti lascerà a scrivere condizioni intuitive (quindi meno probabili da errori) e chiare agli ottimizzatori del database, consentendo di determinare piani di esecuzione ottimali e utilizzare gli indici.

Ad esempio, se la tua query accetta una specifica del giorno di input e deve restituire tutti i record che rientrano in tale data, codifichi come:

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

Cercare di scrivere la logica usando TRA rischi di prestazioni e / o codice errato. Tre passi falsi comuni:

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

Questo è quasi certamente un bug: l'utente si aspetta di vedere solo i record per una determinata data, ma un giorno finirà con un rapporto contenente i record delle 12:00 del giorno successivo.

2) WHERE TRUNC(DATE_FIELD) = :dt

Fornisce la risposta giusta, ma l'applicazione della funzione a DATE_FIELD renderà inutile gran parte dell'indicizzazione / delle statistiche (anche se a volte i DBA cercheranno di aiutare aggiungendo indici basati sulle funzioni ai campi della data - bruciando ancora ore-uomo e spazio su disco e aggiungendo overhead a IUD operazioni sul tavolo)

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

Tom Kyte, straordinario guru di Oracle, consiglia questa soluzione tutt'altro che elegante (IMO). Funziona alla grande finché non passi tutto il giorno a scoprire che "1-1 / 24/06/60" in una query che fornisce risultati incompleti ... o fino a quando non lo usi accidentalmente su un campo TIMESTAMP. Inoltre, è un po 'proprietario; compatibile con il tipo di dati DATE di Oracle (che tiene traccia del secondo), ma deve essere adattato alla precisione DATE / TIME dei diversi prodotti di database.

SOLUZIONE: presentare una petizione al comitato SQL ANSI per migliorare le specifiche del linguaggio SQL modificando la sintassi TRA per supportare la specifica delle alternative al valore predefinito CHIUSO / INCLUSIVO. Qualcosa del genere farebbe il trucco:

expr1 TRA espr2 [ INCL [USIVE] | EXCL [USIVE]] E expr3 [ INCL [USIVE] | EXCL [USIVE]]

Considera quanto diventa facile esprimere WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE(o solo WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL)

Forse ANSI SQL: 2015?


Questa risposta è un saggio consiglio.
Basil Bourque,

@KevinKirkPatrick - Ottima risposta! Ti suggerisco anche di provare a trovare la documentazione decisionale come prova obiettiva del perché originale.
Todd,

3
Personalmente mi piace il exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3modo in cui riesci a mantenere l'operatore tra in modo da sapere che è un predicato a distanza, e il predicato della disuguaglianza assicura che sia semi aperto.
Sentinel,

@Sentinel, Nice! Non mi dichiarerò prematuramente un convertito, ma terrò sicuramente a mente questa variante per quando prossimo codice condizioni di intervallo di date. A prima vista, ha un fascino linguistico maggiore di exp1> = exp2 AND exp1 <exp3; e ovviamente risolve i problemi con TRA ugualmente bene. Sarei interessato se qualche ottimizzatore mostrasse una maggiore "comprensione" di una variazione rispetto all'altra; certamente, sembra plausibile che i tuoi possano dare risultati migliori anche in questo senso (anche se, francamente, sarei piuttosto deluso
dall'ottimizzatore

@KevinKirkpatrick Non li ho mai profilati per accertare se ci sono differenze, e anche io sarei deluso se ci fossero.
Sentinella

8

Sia inclusive ( a <= x <= b) che exclusive ( a < x < b) sono quasi ugualmente comuni, quindi quando hanno creato gli standard hanno semplicemente dovuto sceglierne uno. "Between" in inglese comune è in genere inclusivo e un'istruzione SQL è intesa come simile a una frase inglese, quindi inclusivo è stata una scelta sensata.


4
In realtà l'uso in inglese è ancora più contrastato quando hai lasciato Half-Open. Quando diciamo "il pranzo è tra mezzogiorno e le 13:00" intendiamo a metà aperto in quanto ci si aspetta che torni in classe / lavoro al momento delle 13:00: 00.000, con l'interruzione che salirà ma non includerà il primo momento di l'ora dell'una. a <= x < bè mezzo aperto.
Basil Bourque,

1
@BasilBourque: ciò potrebbe essere dovuto a una precisione infinita, ad esempio il pranzo è tra mezzogiorno e le 12: 59: 99.9999999999999 ....
Brendan,

@Brendan Sì, stai affermando il mio punto. L'infinita (o ambigua) precisione è uno dei problemi che viene gestito usando l'approccio semi-aperto per definire un arco di tempo. Il punto qui è che nella conversazione in inglese gestiamo intuitivamente le gamme aperte e chiuse (come menzionato in questa risposta) così come le gamme semiaperte senza pensarci troppo. Ogni approccio ha uno scopo. Questo è il motivo per cui la definizione SQL di BETWEEN non è ottimale. Idealmente, SQL dovrebbe seguire il suggerimento di KevinKirkpatrick .
Basil Bourque,

2
Si suppone che SQL sia simile all'inglese e sebbene inclusivo ed esclusivo possa essere ugualmente comune, è un linguaggio di query per analisti e programmatori. Come programmatore, penso che sia definito in modo errato, ma non importa, evito comunque di usare "TRA". Non un grande affare.
Todd,

5

L'operatore non viene chiamato ∩[a,b), si chiama BETWEEN, quindi è considerevolmente più appropriato che la sua semantica sia quella della frase inglese "è tra" che quella del predicato matematico "è nell'intervallo semi-aperto".


È necessario considerare tutte le applicazioni, non solo le applicazioni inglesi per i set di numeri interi. "tra 1 e 10", "tra mezzogiorno e 13:00", "tra 1.0 e 5.0" (grammi). "tra 5.50 e 10.30" (dollari). Le quantità continue sarebbero logicamente (in inglese) ritenute esclusive.
Todd,

1
Il problema è che l' BETWEENoperatore non usa la semantica della frase inglese "is between". In inglese "tra" è il tempo, lo spazio o l'intervallo che separa le cose (cioè è esclusivo ). Se si tenta di calciare un goal, la palla deve passare tra i pali per segnare. Se colpisci il palo senza passare tra di loro, nessun punteggio per te.
Disilluso il

1
@CraigYoung come suggerisce la risposta accettata (e sono d'accordo), "se dico" Scegli un numero tra 1 e 10 ", la maggior parte delle persone includerà i numeri 1 e 10 [nella loro gamma di possibili risposte]". In un dominio spaziale sono d'accordo con te, ma per i numeri direi che è diverso. Meglio per la lingua inglese e l'uso di qui però!
AakashM,

@AakashM Il mio punto è che hai avanzato un'affermazione sulla lingua inglese che è semplicemente falsa dalla definizione del dizionario della parola "tra", per giustificare la semantica della programmazione. Il fatto che ci sia una comprensione comune della frase "tra 1 e 10" ha meno a che fare con il significato di "tra" e più a che fare con le posizioni 1 e 10 nel sistema dei numeri decimali. La "correzione automatica" del cervello umano ignora che "tra" esclude gli end point in questo caso perché sembra ridicolo significare "da 2 a 9". Prova lo stesso con "tra 13 e 24". O anche "tra 0 e 11".
Disilluso il

Tra te e me, le affermazioni categoriche sui linguaggi naturali non sono generalmente sicure.
AakashM,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.