SQL:BETWEEN 与 <= 和 >=

发布于 2024-08-08 20:58:58 字数 482 浏览 2 评论 0 原文

在 SQL Server 2000 和 2005 中:

  • 这两个 WHERE 子句有什么区别?
  • 我应该在哪些场景下使用哪一个?

查询 1:

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

查询 2:

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

(编辑:第二个 Eventdate 最初丢失,因此查询在语法上是错误的)

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

鸩远一方 2024-08-15 20:58:58

它们是相同的:BETWEEN 是问题中较长语法的简写,其中包含两个值 (EventDate >= '10/15/2009' 和 EventDate <= '10/19 /2009')。

使用另一种较长的语法,其中 BETWEEN 不起作用,因为不应包含一个或两个值,例如

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

(注意 < 而不是 <=< /code> 在第二个条件中。)

处理 DATETIME

然而,当处理 DATETIME (相对于 DATE)时,结果可能并不直观。
如果 EventDate 恰好是 DATETIME,则比较与时间 (!)

EventDate BETWEEN '10/15/2009' AND '10/18/2009 '

实际上会变成:

EventDate BETWEEN '2009-10-15 00:00' 和 '2009-10-18 00:00'

因为没有指定时间。这将有效地排除2009 年 10 月 18 日的所有内容。

在这种情况下,正确的表达式为:

EventDate BETWEEN '2009-10-15 00:00' and '2009-10-18 23:59:59'

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.)

Dealing with DATETIME

When dealing with DATETIME (vs. DATE) the result might not be intuitive however.
If EventDate happens to be a DATETIME the comparison is done with the time (!)

EventDate BETWEEN '10/15/2009' AND '10/18/2009'

will in fact become:

EventDate BETWEEN '2009-10-15 00:00' and '2009-10-18 00:00'

as no time has specified. This will effectively exclude everything on 10/18/2009.

The proper expression in that case would be:

EventDate BETWEEN '2009-10-15 00:00' and '2009-10-18 23:59:59'

雨轻弹 2024-08-15 20:58:58

他们是一样的。

需要注意的一件事是,如果您针对 DATETIME 使用此选项,则结束日期的匹配将是当天的开始:

<= 20/10/2009

与:(

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

匹配 <代码><= 20/10/2009 00:00:00.000)

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)

温柔嚣张 2024-08-15 20:58:58

尽管 BETWEEN 易于阅读和维护,但我很少推荐使用它,因为它是一个闭区间,并且正如前面提到的,这可能是日期的问题 - 即使没有时间组件。

例如,在处理每月数据时,通常会比较 BETWEEN first AND last 的日期,但实际上,这通常更容易编写 dt >= first AND dt next-first(这也解决了时间部分问题) - 因为确定last通常比确定next-first(通过减去一天)长一步。

此外,另一个问题是下限和上限确实需要以正确的顺序指定(即BETWEEN low AND high)。

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).

晨曦÷微暖 2024-08-15 20:58:58

通常,没有区别 - 并非所有 RDBMS 平台都支持 BETWEEN 关键字,但如果支持,则两个查询应该相同。

由于它们是相同的,因此在速度或其他方面实际上没有区别 - 使用您认为更自然的那个。

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.

孤千羽 2024-08-15 20:58:58

正如@marc_s、@Cloud 等人提到的。对于封闭范围来说,它们基本上是相同的。

但是任何小数时间值都可能会导致封闭范围(大于或等于和小于或等于)的问题,而不是半开范围(大于或等于和小于),最终值最后可能的时刻之后。

因此,为了避免查询应重写为:

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

由于 BETWEEN 不适用于半开间隔,因此我总是仔细查看使用它的任何日期/时间查询,因为它可能是一个错误。

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.

祁梦 2024-08-15 20:58:58

我对 BETWEEN 有一点偏好,因为它可以让读者立即清楚地知道您正在检查一个字段的范围。如果表中具有相似的字段名称,则尤其如此。

比如说,如果我们的表同时具有 transactiondatetransitiondate,如果我读到,

transactiondate between ...

我立即知道测试的两端都针对这一字段。

如果我阅读,

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

我必须花额外的时间来确保这两个字段相同。

此外,随着时间的推移对查询进行编辑,马虎的程序员可能会将这两个字段分开。我见过很多查询都说“

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

如果他们尝试使用 BETWEEN”,当然,这将是一个语法错误并立即修复。

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.

清风疏影 2024-08-15 20:58:58

我认为唯一的区别是每个查询的语法糖量。 BETWEEN 只是一种巧妙的表达方式,与第二个查询完全相同。

可能存在一些我不知道的 RDBMS 特定差异,但我真的不这么认为。

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.

您的好友蓝忘机已上羡 2024-08-15 20:58:58

从逻辑上来说,根本没有区别。
在性能方面——通常在大多数 DBMS 上——根本没有区别。

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

比忠 2024-08-15 20:58:58

有无限的逻辑上等价的陈述,但我会考虑三个(左右)。

情况 1:按标准顺序进行两次比较(评估顺序固定)

A >= MinBound AND A <= MaxBound

情况 2:语法糖(评估顺序不是由作者选择)

MinBound 和 MaxBound 之间

情况 3:按受过教育的顺序进行两次比较(在写入时选择的评估顺序)

A >= MinBound AND A <= MaxBound

A <= MaxBound AND A >= MinBound

根据我的经验,案例 1 和案例 2 在性能上没有任何一致或显着的差异,因为它们不了解数据集。

然而,案例 3 可以极大地缩短执行时间。具体来说,如果您正在处理大型数据集,并且碰巧对 A 是否更有可能大于 MaxBound 还是小于 A 有一些启发式知识,通过使用案例 3 并相应地排序比较,您可以显着缩短执行时间。

我的一个用例是查询具有非索引日期的大型历史数据集,以获取特定时间间隔内的记录。在编写查询时,我将很好地了解指定间隔之前或指定间隔之后是否存在更多数据,并可以相应地排序比较。根据数据集的大小、查询的复杂性以及第一次比较过滤的记录量,我的执行时间减少了一半。

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.

嗼ふ静 2024-08-15 20:58:58

在这种情况下, col BETWEEN ... AND ...col <= ... 和 col >= ... 是等效的。


SQL 标准还定义了 T461 对称BETWEEN 谓词

 <谓词部分 2 之间> ::=
 [ 不 ] 之间 [ 不对称 |对称]
 <行值谓词> AND <行值谓词>

Transact-SQL 不支持此功能。

BETWEEN 要求对值进行排序。例如:

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

<=>

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

另一方面:

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

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

它的工作方式与正常的 BETWEEN 完全相同,但在对比较值进行排序之后。

db<>fiddle 演示

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文