web-dev-qa-db-fra.com

Pourquoi SQL BETWEEN est-il inclus plutôt que semi-ouvert?

Intervalles semi-ouverts (ou semi-ouverts, semi-fermés , semi-délimités ) ([a,b), Où xappartient à l'intervalle si a <= x < b) sont assez courants en programmation, car ils ont de nombreuses propriétés pratiques.

Quelqu'un peut-il fournir une justification qui explique pourquoi le BETWEEN de SQL utilise un intervalle fermé ([a,b])? C'est esp. gênant pour les dates. Pourquoi voudriez-vous que BETWEEN se comporte comme ça?

48
alex

Je pense que l'inclusion BETWEEN est plus intuitive (et apparemment, les concepteurs SQL aussi) 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 en fait 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 la sémantique semi-ouverte aurait été beaucoup plus déroutante pour eux.

49
Oleksi

QUESTION: Pourquoi SQL BETWEEN est-il inclusif?

RÉPONSE: Parce que les concepteurs du langage SQL ont pris une mauvaise décision de conception, en ce sens qu'ils n'ont pas fourni de syntaxe qui permettrait 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 soit modifiée, n'utilisez pas ENTRE entre dates et heures. Prenez plutôt l'habitude de coder les comparaisons de plages DATE en tant que conditions indépendantes sur les limites de début et de fin de votre plage BETWEEN. C'est un peu verbeux, mais vous laisserez des conditions d'écriture intuitives (donc moins susceptibles d'être boguées) et claires pour les optimiseurs de base de données, permettant de déterminer des plans d'exécution optimaux et d'utiliser des index.

Par exemple, si votre requête accepte une spécification de jour d'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 présente des problèmes de performances et/ou du code bogué. Trois faux pas courants:

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

Il s'agit presque certainement d'un bogue - l'utilisateur s'attend à ne voir que les enregistrements pour une date particulière, mais un jour se terminera avec un rapport contenant des enregistrements à partir de midi le lendemain.

2) WHERE TRUNC(DATE_FIELD) = :dt

Donne la bonne réponse, mais l'application de la fonction à DATE_FIELD rendra la plupart des indexations/statistiques inutiles (bien que parfois les administrateurs de base de données essaieront d'aider en ajoutant des index basés sur les fonctions aux champs de date - brûlant toujours des heures-homme et de l'espace disque et en ajoutant des frais généraux au DIU 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 moins qu'élégante (IMO). Fonctionne très bien jusqu'à ce que vous passiez toute la journée à trouver "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 jusqu'au second), mais doit être ajusté à la précision DATE/TIME des différents produits de base de données.

SOLUTION: demander au comité ANSI SQL d'améliorer les spécifications du langage SQL en modifiant la syntaxe BETWEEN pour 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 à quel point il devient facile d'exprimer WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE (Ou simplement WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL)

Peut-être ANSI SQL: 2015?

30
KevinKirkpatrick

Les deux inclus (a <= x <= b) et exclusif (a < x < b) sont à peu près tout aussi courants, donc lors de l'élaboration des normes, ils devaient simplement en choisir une. "Entre" en anglais courant est généralement inclusif, et une instruction SQL est censée se lire comme une phrase anglaise, donc inclusif était un choix judicieux.

8
Matt S

L'opérateur n'est pas appelé ∩[a,b), il s'appelle BETWEEN, il est donc beaucoup plus approprié que sa sémantique soit celle du expression anglaise "se situe entre" que celles du prédicat mathématique "est en semi-ouvert intervalle".

5
AakashM