161

In SQL Server 2000 and 2005:

  • what is the difference between these two WHERE clauses?
  • which one I should use on which scenarios?

Query 1:

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

Query 2:

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

(Edit: the second Eventdate was originally missing, so the query was syntactically wrong)

Oreo
  • 529
  • 3
  • 16
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • 2
    This is a quasi duplicate with http://stackoverflow.com/questions/1572840/sql-between-v1-and-v2 – mjv Oct 27 '09 at 11:47
  • 7
    not really, the handling of datetime is slightly different, plus that was for SQL server 2008, and there is no way Shyju could be certain without asking that the answer would be the same for previous versions. – Irfy Oct 27 '09 at 11:54

10 Answers10

164

They are identical: BETWEEN is a shorthand for the longer syntax in the question that includes both values (EventDate >= '10/15/2009' and EventDate <= '10/19/2009').

Use an alternative longer syntax where BETWEEN doesn't work because one or both of the values should not be included e.g.

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

(Note < rather than <= in second condition.)

Tony Andrews
  • 129,880
  • 21
  • 220
  • 259
  • 27
    I would add that I strongly recommend never using BETWEEN unless you are dealing with the DATE data type or have otherwise guaranteed that your datetime values will never have a time component. Being consistent about this will make it less likely that you'll use BETWEEN by mistake instead of >= and <, and either get some data in the query that you didn't mean to, or think that you were getting an additional day of data when you're not... – Aaron Bertrand Oct 27 '09 at 12:44
  • 2
    Would there be a second compiler step as BETWEEN gets converted to conditionals? I understand this is a bit pedantic but would there be an additional overhead? – James Scott Aug 11 '16 at 14:48
  • How can one say they're identical if they aren't?!? – xmashallax Sep 16 '16 at 12:43
  • 1
    @xmashallax because they are? How are they not? – Tony Andrews Sep 16 '16 at 12:51
  • OP asked if <=, >= and BETWEEN are equal. You say yes, but in your note at the end you basically say no). Am I missing something here?!? `'2016-09-19' <= CURDATE() AND '2016-09-19' >= CURDATE()` will pass, `CURDATE() BETWEEN '2016-09-19' AND '2016-09-19'` will not. – xmashallax Sep 19 '16 at 06:31
  • @xmashallax You are indeed missing something here! The OP asked if there was any difference between `between` and `>=, <=` and I said there in not, they are identical. I then went on to say that for a *different* condition like `>=, <` (note: `<` not `<=`) then you cannot use `between`. I think I added that in response to a comment that asked me to. – Tony Andrews Sep 19 '16 at 09:02
  • @xmashallax Can you explain why (you say) "`'2016-09-19' <= CURDATE() AND '2016-09-19' >= CURDATE()` will pass, `CURDATE() BETWEEN '2016-09-19' AND '2016-09-19'` will not"? – Tony Andrews Sep 19 '16 at 09:08
  • But your second (<) example is exactly what BETWEEN behaves like. Your first (<=) one is not working for me. I googled if <=,>= and BETWEEN were identical, found this answer, changed my code and found an example that proves to me that they aren't identical ... that's my problem here. – xmashallax Sep 19 '16 at 11:33
  • 2
    Strange...I think I got confused by the question, the writing of the answer, the comments and the fact that my code obviously has a bug now =) – xmashallax Sep 19 '16 at 11:48
  • Dredging up the past, I know, but ... @xmashallax: The second version posted by Tony allows for testing against dates that have a time element, though the version posted will only check for dates from `2009/10/15 00:00:00` to `2009/10/17 23:59:59.999` (note: not `2009/10/18 23:59:59.999`) inclusive. Using `BETWEEN` in such circumstances would not work properly as this is an inclusive (i.e. >= and <=) operator; any records that have a date and time value of `2009/10/18 00:00:00` would be included in the result set. – Paul Feb 01 '17 at 11:30
  • References: [Microsoft Docs](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/between-transact-sql); [W3 Schools](https://www.w3schools.com/sql/sql_between.asp) – AndyS May 16 '17 at 09:32
  • 3
    basically to make sure that everyone reading this post does not get confused, the `between` clause is **inclusive of both dates**, while when you use the `>` and `<` syntax, you can **exclude any of the two dates** at the start and end of the range. – Michele La Ferla Dec 30 '20 at 12:59
  • I misread this answer and used between incorrectly for months. This is not your fault, however others may skim your answer and draw the same conclusions I did. May I suggest writing one code block which shows the syntax which IS equivalent to between, and then have a code block which shows syntax which IS NOT equivalent to between. – jmtennant Jun 02 '21 at 17:53
  • There are claims that the AND operator, in opposition to the BETWEEN, does not make efficient use of the indexes here: https://www.datacamp.com/community/tutorials/sql-tutorial-query But that does not seem to make any sense considering it is just syntactic sugar, any comment on indexing? – Heberto Mayorquin Nov 18 '21 at 14:20
  • 1
    @RamonMartinez I had never heard that. I can imagine that some DBMS might recognise that a BETWEEN filters a small range of indexed values, but with the separate predicates `d >= v1 and d <= v2` might just see 2 separate predicates, neither of which benefits from the index on its own. But that's just a guess! – Tony Andrews Nov 18 '21 at 15:11
43

They are the same.

One thing to be careful of, is if you are using this against a DATETIME, the match for the end date will be the beginning of the day:

<= 20/10/2009

is not the same as:

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

(it would match against <= 20/10/2009 00:00:00.000)

Paul Stephenson
  • 67,682
  • 9
  • 49
  • 51
Irfy
  • 2,469
  • 4
  • 25
  • 31
  • You can simply use between '2009-10-20' and '2009-10-21' in that case to capture the day – David Andrei Ned Nov 24 '16 at 10:32
  • 4
    @DavidAndreiNed that would also match '2009-10-21 00:00:00.000' - probably not what you want. – Hans Kesting Jan 25 '17 at 16:04
  • 2
    You would want field BETWEEN '2009-10-20 00:00:00' AND '2009-10-20 23:59:59' or field >= '2009-10-20 00:00:00' AND field <= '2009-10-20 23:59:59' to be absolutely certain. – geilt Mar 12 '19 at 07:02
  • @geilt Your examples would miss anything that occurred within the last second of the day... ie: in between 23:59:59 and 00:00:00 on the next day. – Seth Flowers Jun 19 '19 at 13:16
  • 00:00:00 is the start of next day and why I use >= and <= and not > or <.But if you meant microseconds and you stores them then you would want to put the last and final microsecond as well. – geilt Aug 20 '19 at 07:04
  • @geilt, I think to be absolutely certain you would use < '2009-10-21' so that everything before 10/21 00:00:00 is included, and there's no need to worry about microseconds. – Phil Goldenberg Jul 28 '21 at 17:01
17

Although BETWEEN is easy to read and maintain, I rarely recommend its use because it is a closed interval and as mentioned previously this can be a problem with dates - even without time components.

For example, when dealing with monthly data it is often common to compare dates BETWEEN first AND last, but in practice this is usually easier to write dt >= first AND dt < next-first (which also solves the time part issue) - since determining last usually is one step longer than determining next-first (by subtracting a day).

In addition, another gotcha is that lower and upper bounds do need to be specified in the correct order (i.e. BETWEEN low AND high).

Cade Roux
  • 88,164
  • 40
  • 182
  • 265
4

Typically, there is no difference - the BETWEEN keyword is not supported on all RDBMS platforms, but if it is, the two queries should be identical.

Since they're identical, there's really no distinction in terms of speed or anything else - use the one that seems more natural to you.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
4

As mentioned by @marc_s, @Cloud, et al. they're basically the same for a closed range.

But any fractional time values may cause issues with a closed range (greater-or-equal and less-or-equal) as opposed to a half-open range (greater-or-equal and less-than) with an end value after the last possible instant.

So to avoid that the query should be rewritten as:

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

Since BETWEEN doesn't work for half-open intervals I always take a hard look at any date/time query that uses it, since its probably an error.

devstuff
  • 8,277
  • 1
  • 27
  • 33
4

I have a slight preference for BETWEEN because it makes it instantly clear to the reader that you are checking one field for a range. This is especially true if you have similar field names in your table.

If, say, our table has both a transactiondate and a transitiondate, if I read

transactiondate between ...

I know immediately that both ends of the test are against this one field.

If I read

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

I have to take an extra moment to make sure the two fields are the same.

Also, as a query gets edited over time, a sloppy programmer might separate the two fields. I've seen plenty of queries that say something like

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

If they try this with a BETWEEN, of course, it will be a syntax error and promptly fixed.

Pang
  • 9,564
  • 146
  • 81
  • 122
Jay
  • 26,876
  • 10
  • 61
  • 112
3

I think the only difference is the amount of syntactical sugar on each query. BETWEEN is just a slick way of saying exactly the same as the second query.

There might be some RDBMS specific difference that I'm not aware of, but I don't really think so.

pyrocumulus
  • 9,072
  • 2
  • 43
  • 53
2

Logically there are no difference at all. Performance-wise there are -typically, on most DBMSes- no difference at all.

mjv
  • 73,152
  • 14
  • 113
  • 156
1

There are infinite logically equivalent statements, but I'll consider three(ish).

Case 1: Two Comparisons in a standard order (Evaluation order fixed)

A >= MinBound AND A <= MaxBound

Case 2: Syntactic sugar (Evaluation order is not chosen by author)

A BETWEEN MinBound AND MaxBound

Case 3: Two Comparisons in an educated order (Evaluation order chosen at write time)

A >= MinBound AND A <= MaxBound

Or

A <= MaxBound AND A >= MinBound

In my experience, Case 1 and Case 2 do not have any consistent or notable differences in performance as they are dataset ignorant.

However, Case 3 can greatly improve execution times. Specifically, if you're working with a large data set and happen to have some heuristic knowledge about whether A is more likely to be greater than the MaxBound or lesser than the MinBound you can improve execution times noticeably by using Case 3 and ordering the comparisons accordingly.

One use case I have is querying a large historical dataset with non-indexed dates for records within a specific interval. When writing the query, I will have a good idea of whether or not more data exists BEFORE the specified interval or AFTER the specified interval and can order my comparisons accordingly. I've had execution times cut by as much as half depending on the size of the dataset, the complexity of the query, and the amount of records filtered by the first comparison.

miken32
  • 42,008
  • 16
  • 111
  • 154
LanchPad
  • 257
  • 3
  • 10
  • Um, what? Case 3 doesn't share the same logic as Case 1 and Case 2. If you want to see if `A` is greater than both bounds, then just check if the `A` is greater than the `MaxBound`. Your post needs some adjusting. – mickmackusa Jul 28 '19 at 23:26
  • Looks like I made a typo on the equality operators. Good catch. – LanchPad Aug 27 '19 at 19:47
0

In this scenario col BETWEEN ... AND ... and col <= ... and col >= ... are equivalent.


SQL Standard defines also T461 Symmetric BETWEEN predicate:

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

Transact-SQL does not support this feature.

BETWEEN requires that values are sorted. For instance:

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

<=>

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

On the other hand:

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

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

It works exactly as the normal BETWEEN but after sorting the comparison values.

db<>fiddle demo

Community
  • 1
  • 1
Lukasz Szozda
  • 162,964
  • 23
  • 234
  • 275