0

考虑这个名为 的表easy_drinks

+------------------+
| drink_name       |
+------------------+
| Kiss on the Lips |
| Hot Gold         |
| Lone Tree        |
| Greyhound        |
| Indian Summer    |
| Bull Frog        |
| Soda and It      |
| Blackthorn       |
| Blue Moon        |
| Oh My Gosh       |
| Lime Fizz        |
+------------------+

这样的查询,

 select drink_name from easy_drinks where drink_name BETWEEN 'G' and 'O';

结果是

+------------------+
| drink_name       |
+------------------+
| Kiss on the Lips |
| Hot Gold         |
| Lone Tree        |
| Greyhound        |
| Indian Summer    |
| Lime Fizz        |
+------------------+

以开头的饮料名称O不包含在结果中。但根据手册

expr 介于最小值和最大值之间

如果 expr 大于或等于 min 且 expr小于或等于 max,则 BETWEEN 返回 1,否则返回 0。如果 expr 大于或等于 min 且 expr 小于或等于 max ,则 BETWEEN >返回1,否则返回 0。

为什么查询会给出这样的结果?

我已经通过解释时间戳和日期行为的问题。在这种情况下是什么原因?

4

2 回答 2

2

tl;博士

不要将 BETWEEN 用于字符串

其中drink_name >= 'G' 和drink_name <'P';

为什么?

O 用尾随空格有效地扩展以匹配列。所以

'O                  '

是之前

'Oh My Gosh'

所以你需要

where drink_name BETWEEN 'G' and 'OZ';

如果你有一个叫的饮料,Ozymandias那么这将行不通。所以:

where drink_name BETWEEN 'G' and 'OZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ';

但是,我们可以安全地假设没有饮料叫P而且有很多空格吗?
这是不可理解的。

select drink_name from easy_drinks
where drink_name BETWEEN 'G' and 'P';

显而易见的选择可能是使用LEFT仅比较第一个字母

select drink_name from easy_drinks
where LEFT(drink_name, 1) BETWEEN 'G' and 'O';

但这将阻止使用drink_name 上的任何索引。

于 2013-05-23T09:33:26.207 回答
2

这是发现发生了什么的更简单的方法

select drink_name, drink_name >='G', drink_name <='O'
from easy_drinks
order by 1;

主要结果是:

  • Greyhound是 >= 'G'
  • Oh My Gosh不是< = 'O'

一旦你考虑它就很有意义。在字典中,单个 O 条目始终是字母 O 中的第一项。

你可能想要这样的东西

select drink_name
from easy_drinks
where SUBSTRING(drink_name, 1, 1) BETWEEN 'G' and 'O';

编辑:

我完全忘记了LEFT(drink_name, 1),这是一个方便的捷径SUBSTRING(drink_name, 1, 1)

于 2013-05-23T09:49:13.350 回答