SQL: ZWISCHEN vs <= und> =

111

In SQL Server 2000 und 2005:

  • Was ist der Unterschied zwischen diesen beiden WHEREKlauseln?
  • Welches sollte ich in welchen Szenarien verwenden?

Abfrage 1:

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

Abfrage 2:

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

(Bearbeiten: Das zweite Ereignisdatum fehlte ursprünglich, daher war die Abfrage syntaktisch falsch.)

Shyju
quelle
1
Dies ist ein Quasi-Duplikat mit stackoverflow.com/questions/1572840/sql-between-v1-and-v2
mjv
6
Nicht wirklich, die Behandlung von datetime ist etwas anders, und das war für SQL Server 2008, und Shyju kann auf keinen Fall sicher sein, ohne zu fragen, ob die Antwort für frühere Versionen dieselbe wäre.
Irfy

Antworten:

119

Sie sind identisch: BETWEENist eine Abkürzung für die längere Syntax in der Frage.

Verwenden Sie eine alternative längere Syntax, bei BETWEENder z

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

(Beachten Sie <eher als <=in der zweiten Bedingung.)

Tony Andrews
quelle
19
Vielleicht sollten Sie betonen, dass die zweite Bedingung '<' ist. Ich brauchte einige Zeit, um den Unterschied zu erkennen.
Zendar
21
Ich würde hinzufügen, dass ich dringend empfehle, niemals ZWISCHEN zu verwenden, es sei denn, Sie haben es mit dem Datentyp DATE zu tun oder auf andere Weise garantiert, dass Ihre datetime-Werte niemals eine Zeitkomponente haben. Wenn Sie diesbezüglich konsistent sind, ist es weniger wahrscheinlich, dass Sie versehentlich ZWISCHEN anstelle von> = und <verwenden und entweder einige Daten in der Abfrage abrufen, die Sie nicht beabsichtigt haben, oder glauben, dass Sie einen zusätzlichen Tag erhalten Daten, wenn Sie nicht ...
Aaron Bertrand
1
Würde es einen zweiten Compilerschritt geben, wenn ZWISCHEN in Bedingungen konvertiert wird? Ich verstehe, dass dies ein bisschen pedantisch ist, aber würde es einen zusätzlichen Overhead geben?
James Scott
1
@xmashallax weil sie sind? Wie geht es ihnen nicht?
Tony Andrews
2
Seltsam ... Ich denke, ich war verwirrt von der Frage, dem Schreiben der Antwort, den Kommentaren und der Tatsache, dass mein Code jetzt offensichtlich einen Fehler hat =)
xmashallax
37

Sie sind gleich.

Eine Sache, auf die Sie achten sollten, ist, wenn Sie dies gegen eine DATETIME verwenden, wird das Match für das Enddatum der Anfang des Tages sein:

<= 20/10/2009

ist nicht dasselbe wie:

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

(es würde gegen passen <= 20/10/2009 00:00:00.000)

Irfy
quelle
In diesem Fall können Sie einfach zwischen '2009-10-20' und '2009-10-21' verwenden, um den Tag festzuhalten
David Andrei Ned
4
@DavidAndreiNed, das auch zu '2009-10-21 00: 00: 00.000' passen würde - wahrscheinlich nicht das, was Sie wollen.
Hans
2
Sie möchten das Feld ZWISCHEN '2009-10-20 00:00:00' UND '2009-10-20 23:59:59' oder das Feld> = '2009-10-20 00:00:00' UND das Feld <= '2009-10-20 23:59:59' um absolut sicher zu sein.
Geilt
@geilt Ihre Beispiele würden alles vermissen, was in der letzten Sekunde des Tages passiert ist ... dh: zwischen 23:59:59 und 00:00:00 am nächsten Tag.
Seth Flowers
00:00:00 ist der Beginn des nächsten Tages und warum ich> = und <= und nicht> oder <verwende. Wenn Sie jedoch Mikrosekunden gemeint haben und diese speichern, möchten Sie auch die letzte und letzte Mikrosekunde eingeben.
Geilt
14

Obwohl BETWEENes leicht zu lesen und zu warten ist, empfehle ich die Verwendung selten, da es sich um ein geschlossenes Intervall handelt. Wie bereits erwähnt, kann dies ein Problem mit Datumsangaben sein - auch ohne Zeitkomponenten.

Wenn Sie beispielsweise mit monatlichen Daten arbeiten, ist es häufig üblich, Daten zu vergleichen. BETWEEN first AND lastIn der Praxis ist dies jedoch normalerweise einfacher zu schreiben dt >= first AND dt < next-first(wodurch auch das Zeitteilproblem gelöst wird), da das Bestimmen lastnormalerweise einen Schritt länger ist als das Bestimmen next-first(durch Subtrahieren eines Tages). .

Ein weiteres Problem ist, dass die unteren und oberen Grenzen in der richtigen Reihenfolge (dh BETWEEN low AND high) angegeben werden müssen.

Cade Roux
quelle
4

Normalerweise gibt es keinen Unterschied - das BETWEENSchlüsselwort wird nicht auf allen RDBMS-Plattformen unterstützt, aber wenn dies der Fall ist, sollten die beiden Abfragen identisch sein.

Da sie identisch sind, gibt es wirklich keinen Unterschied in Bezug auf Geschwindigkeit oder irgendetwas anderes - verwenden Sie den, der Ihnen natürlicher erscheint.

marc_s
quelle
4

Wie von @marc_s erwähnt, haben @Cloud et al. Für einen geschlossenen Bereich sind sie im Grunde gleich.

Jeder Zeitbruchteil kann jedoch Probleme mit einem geschlossenen Bereich (größer oder gleich und kleiner oder gleich ) verursachen, im Gegensatz zu einem halboffenen Bereich (größer oder gleich und kleiner als ) mit einem Endwert nach dem letzter möglicher Augenblick.

Um zu vermeiden, dass die Abfrage wie folgt umgeschrieben wird:

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

Da BETWEENdies nicht für halboffene Intervalle funktioniert, schaue ich mir jede Datums- / Zeitabfrage, die es verwendet, immer genau an, da es wahrscheinlich ein Fehler ist.

devstuff
quelle
4

Ich habe eine leichte Präferenz für, BETWEENweil es dem Leser sofort klar macht, dass Sie ein Feld auf einen Bereich prüfen . Dies gilt insbesondere dann, wenn Ihre Tabelle ähnliche Feldnamen enthält.

Wenn zum Beispiel unsere Tabelle sowohl a transactiondateals auch a hat transitiondate, wenn ich lese

transactiondate between ...

Ich weiß sofort, dass beide Enden des Tests gegen dieses eine Feld sind.

Wenn ich lese

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

Ich muss mir einen zusätzlichen Moment Zeit nehmen, um sicherzustellen, dass die beiden Felder gleich sind.

Wenn eine Abfrage im Laufe der Zeit bearbeitet wird, kann ein schlampiger Programmierer die beiden Felder trennen. Ich habe viele Anfragen gesehen, die so etwas wie sagen

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

Wenn sie dies mit a versuchen BETWEEN, handelt es sich natürlich um einen Syntaxfehler, der umgehend behoben wird.

Jay
quelle
3

Ich denke, der einzige Unterschied ist die Menge an syntaktischem Zucker bei jeder Abfrage. ZWISCHEN ist nur eine raffinierte Art, genau dasselbe wie die zweite Abfrage zu sagen.

Möglicherweise gibt es einen RDBMS-spezifischen Unterschied, den ich nicht kenne, aber ich denke nicht wirklich.

Pyrocumulus
quelle
2

Logischerweise gibt es überhaupt keinen Unterschied. In Bezug auf die Leistung gibt es bei den meisten DBMS normalerweise keinen Unterschied.

mjv
quelle
1

Haftungsausschluss: Alles unten ist nur anekdotisch und stammt direkt aus meiner persönlichen Erfahrung. Jeder, der Lust hat, eine empirisch strengere Analyse durchzuführen, kann diese gerne durchführen und abstimmen, wenn ich es bin. Mir ist auch bewusst, dass SQL eine deklarative Sprache ist und Sie nicht berücksichtigen müssen, wie Ihr Code beim Schreiben verarbeitet wird, aber weil ich meine Zeit schätze, tue ich das auch.

Es gibt unendlich viele logisch äquivalente Aussagen, aber ich werde drei (ish) betrachten.

Fall 1: Zwei Vergleiche in einer Standardreihenfolge (Bewertungsreihenfolge festgelegt)

A> = MinBound UND A <= MaxBound

Fall 2: Syntaktischer Zucker (Bewertungsreihenfolge wird vom Autor nicht gewählt)

EIN ZWISCHEN MinBound UND MaxBound

Fall 3: Zwei Vergleiche in einer gebildeten Reihenfolge (Bewertungsreihenfolge zum Zeitpunkt des Schreibens gewählt)

A> = MinBound UND A <= MaxBound

Oder

A <= MaxBound AND A> = MinBound

Nach meiner Erfahrung weisen Fall 1 und Fall 2 keine konsistenten oder bemerkenswerten Leistungsunterschiede auf, da sie den Datensatz nicht kennen.

Fall 3 kann jedoch die Ausführungszeiten erheblich verbessern. Insbesondere, wenn Sie mit einem großen Datensatz arbeiten und zufällig heuristische Kenntnisse darüber haben, ob A mit größerer Wahrscheinlichkeit größer als MaxBound ist oder kleiner als der MinBound ist , können Sie die Ausführungszeiten spürbar verbessern, indem Sie Fall 3 verwenden und die Vergleiche anordnen entsprechend.

Ein Anwendungsfall, den ich habe, ist das Abfragen eines großen historischen Datensatzes mit nicht indizierten Daten für Datensätze innerhalb eines bestimmten Intervalls. Beim Schreiben der Abfrage habe ich eine gute Vorstellung davon, ob vor dem angegebenen Intervall oder NACH dem angegebenen Intervall weitere Daten vorhanden sind, und kann meine Vergleiche entsprechend anordnen. Die Ausführungszeiten wurden je nach Größe des Datasets, der Komplexität der Abfrage und der Anzahl der durch den ersten Vergleich gefilterten Datensätze um die Hälfte reduziert.

LanchPad
quelle
Ähm, was? Fall 3 hat nicht die gleiche Logik wie Fall 1 und Fall 2. Wenn Sie sehen möchten, ob Abeide Grenzen größer sind, überprüfen Sie einfach, ob die Agrößer als die ist MaxBound. Ihr Beitrag muss angepasst werden.
Mickmackusa
Sieht so aus, als hätte ich einen Tippfehler bei den Gleichheitsoperatoren gemacht. Guter Fang.
LanchPad
0

In diesem Szenario col BETWEEN ... AND ...und col <= ... and col >= ...sind gleichwertig.


SQL Standard definiert auch T461 Symmetric ZWISCHEN Prädikat :

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

Transact-SQL unterstützt diese Funktion nicht.

BETWEENerfordert, dass die Werte sortiert sind. Zum Beispiel:

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

<=>

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

Andererseits:

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

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

Es funktioniert genauso wie normal, BETWEENjedoch nach dem Sortieren der Vergleichswerte.

db <> Geigen-Demo

Lukasz Szozda
quelle