Pourquoi le SQL est-il ENTRE ENTRE inclusif et non semi-ouvert?

45

Les intervalles semi-ouverts (ou semi-ouverts, semi-fermés , semi-délimités ) ( [a,b), où xappartient à l'intervalle ssi a <= x < b) sont assez courants en programmation, car ils possèdent de nombreuses propriétés pratiques.

Quelqu'un peut-il offrir une justification qui explique pourquoi SQL BETWEENutilise un intervalle fermé ( [a,b])? C'est esp. gênant pour les dates. Pourquoi voudriez-vous vous BETWEENcomporter comme ça?

alex
la source
Je suis curieux, quelles propriétés pratiques ont-ils?
phant0m
2
Si ce n'était pas inclusif, comment pourriez-vous facilement interroger tous les noms de famille dans la plage A à D? ou noms W à Z? Pour les nombres compris entre 1 et 10, vous pouvez rechercher 0 <n <11, mais pour les caractères, vous devez utiliser des nombres ASCII? ou unicode? De plus, les index peuvent facilement vous amener au début de vos données.
Jqa
2
Je comprends votre frustration, (StartDate> = '2010-01-01' et StartDate <'2011-01-01'), fonctionne à merveille, utiliser Entre l’équivelent serait (StartDate entre le '2010-01-01' et ' 2010-12-31 23:59:59 '), à la fois volumineux et il faut savoir combien de jours sont en décembre
Todd
1
@ phant0m [a, b) U [c, d) == [a, d). [a: int, b: int) contient exactement des éléments ba. Le commentaire de Todd montre comment ils fonctionnent particulièrement bien pour les rendez-vous (c'est là où ils me manquent le plus). Fondamentalement, lors du codage, les intervalles semi-ouverts ont tendance à être plus simples, plus faciles à utiliser et robustes.
alex
La meilleure réponse aurait dû faire référence à une documentation de décision objective émanant des personnes qui avaient spécifié BETWEEN pour SQL au préalable, en répondant ainsi à Why, plutôt qu'à la réponse subjective choisie.
Todd

Réponses:

48

Je pense que l'inclusion BETWEENest plus intuitive (et apparemment, les concepteurs SQL l'ont fait) qu'un intervalle semi-ouvert. Par exemple, si je dis "Choisissez un nombre entre 1 et 10", la plupart des gens incluront les nombres 1 et 10. L'intervalle ouvert est particulièrement déroutant pour les non-développeurs car il est asymétrique. SQL est parfois utilisé par des non-programmeurs pour faire des requêtes simples, et une sémantique semi-ouverte aurait été beaucoup plus déroutante pour eux.

Oleksi
la source
9
Votre exemple se concentre sur les entiers, pour les nombres décimaux et d'autres quantités délimitées (telles que les dates), le terme entre les deux est ambigu. Si je vous dis que vous avez fait X entre 2012 et 2013, je n'inclue pas 2013 (ou plus précisément le jour 2013-01-01)
Todd
4
@Todd Toute utilisation de ces termes est ambiguë. C'est pourquoi les mathématiciens, les scientifiques et les programmeurs avertis documentent leur intention comme étant "à moitié ouverte" ou similaire. Je pense que la réponse de Oleski est que SQL était à l'origine destiné aux utilisateurs finaux plutôt qu'aux programmeurs (vraiment!). Apparemment, les concepteurs SQL se sont penchés sur une définition qui leur convenait le mieux pour ce public. Mais comme le suggèrent les auteurs de la Question, la semi-ouverture est presque toujours préférable pour travailler avec des plages telles que des périodes de temps.
Basil Bourque
"Je pense qu'inclusif ENTRE est plus intuitif" est subjectif. "Le langage SQL est parfois utilisé par des non-programmeurs pour effectuer des requêtes simples" - Les non-programmeurs doivent également vérifier la spécification.
Todd
La question est également souvent posée "Choisissez un nombre compris entre 1 et 10" (simplement pour éviter toute ambiguïté évidente). En note de côté. Vous dites "choisissez un nombre entre 1 et 10"; la plupart des gens ne choisiraient probablement pas 1 ou 10. D' accord, c'est davantage un problème de psychologie. :) Les gens accepteraient toujours 1 et 10 comme choix valables (en dépit d'être sémantiquement incorrects); mais c'est le résultat d'une interprétation contextuelle en supposant que 1 et 10 sont valides. Si vous deviez dire: "entre 13 et 24" et que vous serez plus susceptible de vous demander si 13 et 24 sont inclus.
Désillusionné le
26

QUESTION: Pourquoi SQL est-il compris entre?

RÉPONSE: Les concepteurs de langage SQL ayant pris une mauvaise décision de conception, ils n’ont pas réussi à fournir une syntaxe permettant aux développeurs de spécifier laquelle des 4 variantes de BETWEEN (fermée, semi-ouverte à gauche, semi-ouverte à droite ou ouverte). ) ils préfèrent.

RECOMMANDATION: À moins que / jusqu'à ce que la norme SQL ne soit modifiée, n'utilisez pas BETWEEN pour les dates / heures. Prenez plutôt l’habitude de coder les comparaisons de plages DATE en tant que conditions indépendantes des limites de début et de fin de votre plage BETWEEN. Ceci est un peu détaillé, mais vous laissera des conditions d’écriture intuitives (donc moins susceptibles d’être boguées) et claires pour les optimiseurs de base de données, ce qui permettra de déterminer les plans d’exécution optimaux et d’utiliser les index.

Par exemple, si votre requête accepte une spécification de jour en entrée et doit renvoyer tous les enregistrements tombés à cette date, vous devez coder comme suit:

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

Essayer d'écrire la logique à l'aide de BETWEEN, de problèmes de performances et / ou de code erroné. Trois faux pas communs:

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

Il s’agit presque certainement d’un bogue: l’utilisateur ne s'attend à voir que les enregistrements correspondant à une date donnée. Pourtant, un jour se terminera avec un rapport contenant des enregistrements à partir de midi le jour suivant.

2) WHERE TRUNC(DATE_FIELD) = :dt

Donne la bonne réponse, mais appliquer la fonction à DATE_FIELD rendra la plupart des index / statistiques inutiles (bien que parfois les administrateurs de bases de données essaient de l'aider en ajoutant des index basés sur les fonctions aux champs de date, tout en consommant toujours plus d'heures de travail et d'espace disque et en augmentant le temps de traitement du stérilet opérations sur la table)

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

Tom Kyte, extraordinaire gourou d’Oracle, recommande cette solution peu élégante (IMO). Fonctionne très bien jusqu'à ce que vous passiez toute la journée à trouver ce "1-1 / 24/06/60" dans une requête qui donne des résultats incomplets ... ou jusqu'à ce que vous l'utilisiez accidentellement sur un champ TIMESTAMP. De plus, c'est un peu propriétaire; compatible avec le type de données DATE d’Oracle (qui suit au second), mais doit être ajusté à la précision DATE / TIME de différents produits de base de données.

SOLUTION: demandez au comité SQL ANSI d'améliorer les spécifications de langage SQL en modifiant la syntaxe BETWEEN afin de prendre en charge la spécification d'alternatives à la valeur par défaut CLOSED / INCLUSIVE. Quelque chose comme ça ferait l'affaire:

expr1 ENTRE Expr2 [ INCL [USIVE] | EXCL [USIVE]] ET expr3 [ INCL [USIVE] | EXCL [USIVE]]

Considérez comme il est facile d’exprimer WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE(ou tout simplement WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL)

Peut-être que ANSI SQL: 2015?

KevinKirkpatrick
la source
Cette réponse est un sage conseil.
Basil Bourque
@ KevinKirkPatrick - excellente réponse! Je vous suggère également d'essayer de trouver la documentation relative à la décision comme preuve objective du pourquoi original.
Todd
3
Personnellement, j'aime bien exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3cette façon de garder l'opérateur entre les deux afin que vous sachiez que c'est un prédicat à distance, et le prédicat d'inégalité garantit qu'il est semi-ouvert.
Sentinel le
@Sentinel, Nice! Je ne vais pas me déclarer prématurément converti, mais je garderai certainement cette variante à l'esprit pour le prochain code des conditions de plage de dates. À première vue, son attrait linguistique est supérieur à celui de exp1> = exp2 AND exp1 <exp3; et résout évidemment les problèmes avec BETWEEN. Je serais intéressé si l'un des optimiseurs montre une plus grande "compréhension" d'une variation par rapport à une autre; certes, il semble plausible que les vôtres donnent de meilleurs résultats à cet égard également (même si, franchement, je serais assez déçu de l'optimiseur qui les traitait différemment)
KevinKirkpatrick le
@KevinKirkpatrick Je ne les ai jamais profilés pour vérifier s'il y a des différences, et moi aussi je serais déçu s'il y en avait.
Sentinel
8

Les deux méthodes inclusive ( a <= x <= b) et exclusive ( a < x < b) sont à peu près communes, il fallait donc en choisir une pour établir les normes. "Entre" en anglais commun est généralement inclusif, et une instruction SQL est conçue pour se lire de la même manière qu'une phrase anglaise. Inclus était donc un choix judicieux.

Matt S
la source
4
En réalité, l’utilisation en anglais est encore plus mitigée si vous avez laissé Half-Open en retrait. Quand nous disons « le déjeuner est entre midi et 13 heures » , nous entendons entrebâillée que vous attendiez de retour en classe / travail au moment de 13: 00: 00.000, avec la pause allant jusqu'à , mais sans compter le premier moment de l'heure une heure. a <= x < best à moitié ouvert.
Basil Bourque
1
@BasilBourque: Cela peut être dû à une précision infinie - par exemple, le déjeuner est entre midi et 12h: 59h99,9999999999999 ....
Brendan
@Brendan Oui, vous faites mon point. La précision infinie (ou ambiguë) est l’un des problèmes traités en utilisant l’approche semi-ouverte pour définir une période. Le point ici est que, dans la conversation anglaise, nous gérons intuitivement les plages ouvertes et fermées (comme indiqué dans cette réponse) ainsi que les plages semi-ouvertes sans trop y penser. Chaque approche sert un but. C'est pourquoi la définition SQL de BETWEEN n'est pas optimale. Idéalement, SQL suivrait la suggestion de KevinKirkpatrick .
Basil Bourque
2
SQL est supposé être de type anglais, et bien que inclusif et exclusif puisse être tout aussi commun, c'est un langage de requête pour les analystes et les programmeurs. En tant que programmeur, je pense que c'est mal défini, mais cela n'a pas vraiment d'importance, j'évite simplement d'utiliser "BETWEEN" de toute façon. Pas un gros problème.
Todd
5

L'opérateur n'est pas appelé ∩[a,b), il est appelé BETWEEN, il est donc bien plus approprié que sa sémantique soit celle de la phrase anglaise "is between" que celle du prédicat mathématique "is in semi-open interval".

AakashM
la source
Il faut prendre en compte toutes les applications, pas seulement les applications anglaises pour les ensembles Integer. "entre 1 et 10", "entre midi et 13 heures", "entre 1,0 et 5,0" (grammes). "entre 5h50 et 10h30" (dollars). Les quantités continues seraient logiquement (anglaisement) supposées exclusives.
Todd
1
Le problème est que l' BETWEENopérateur n'utilise pas la sémantique de la phrase anglaise "is between". En anglais, "between" est le temps, l'espace ou l'intervalle qui sépare les choses (c'est-à-dire qu'il est exclusif ). Si vous essayez de marquer un but, le ballon doit passer entre les poteaux pour marquer. Si vous ne parvenez pas à passer le poteau entre les poteaux, aucun point pour vous.
Désillusionné le
1
@CraigYoung comme le suggère la réponse acceptée (et je suis d'accord), "si je dis" Choisissez un nombre entre 1 et 10 ", la plupart des gens incluront les chiffres 1 et 10 [dans leur gamme de réponses possibles]". Dans le domaine spatial , je suis d'accord avec vous, mais pour les chiffres, je dirais que c'est différent. Mieux pour la langue anglaise et son utilisation qu'ici!
AakashM
@AakashM Mon argument est que vous avez formulé une revendication sur la langue anglaise qui est simplement fausse par la définition du mot "between" dans le dictionnaire pour justifier la sémantique de la programmation. Le fait qu'il existe une compréhension commune de l'expression "entre 1 et 10" a moins à voir avec la signification de "entre" qu'avec davantage avec les positions 1 et 10 dans le système de nombre décimal. La "correction automatique" du cerveau humain ignore que "entre" exclut les points finaux dans ce cas car il semble ridicule de vouloir dire "de 2 à 9". Essayez la même chose avec "entre 13 et 24". Ou même "entre 0 et 11".
Désillusionné le
Entre vous et moi, les affirmations catégoriques sur les langues naturelles sont généralement dangereuses.
AakashM