2014-12-05 4 views
9

Использование Oracle 11gR2 Expression Edition. Мои данные выглядит следующим образом
Oracle NOT BETWEEN для сравнения строк не дает такого же результата, как <= and > =

ordertype 
--------- 
ZOCO 
ZOSA 
ZOST 

Мы пытаемся выяснить, запись, где столбец не между определенным диапазоном значений.

Если я выполнить запрос с < = и> = операторы: SELECT * FROM table where ordertype <= 'ZAAA' OR ordertype >= 'ZZZZ'; тогда я получаю 0 результатов. Это правильный ответ.

Однако, если я использую NOT BETWEEN: SELECT * FROM table where ordertype NOT BETWEEN 'ZAAA' AND 'ZZZZ'; , то это дает несколько хитов.

Мое понимание заключается в том, что оба синтаксиса должны давать одинаковый результат, но это не так. Что мне не хватает? Причина, по которой я хочу использовать NOT BETWEEN, потому что у нашего существующего кода уже есть этот синтаксис, и я не хочу его менять, не понимая причин.

спасибо.


Спасибо за всех, кто разместил. Я снова запустил запросы и после исправления «OR» в первом запросе результаты остались прежними. У меня все еще возникает вопрос, почему сортировка символов Oracle не распознает его, как ожидалось, но мой вопрос, касающийся разницы между NOT BETWEEN и <>, был ложным сигналом. Прошу прощения за путаницу.

+0

Приносим извинения за типографию в моем вопросе выше. Первый запрос, который я хотел написать, был ordertype <= 'ZAAA' OR ordertype> = 'ZZZZ' – user3208146

+0

Спасибо всем, кто разместил. Я снова запустил запросы и после исправления «OR» в первом запросе результаты остались прежними. У меня все еще возникает вопрос, почему сортировка символов Oracle не распознает его, как ожидалось, но мой вопрос, касающийся разницы между NOT BETWEEN и <>, был ложным сигналом. – user3208146

+1

Теперь, после того, как вы изменили 'and' на' or', я вполне уверен, что оба оператора действительно возвращают одни и те же записи. Не могли бы вы запустить http://sqlfiddle.com/#!4/d8ac4/1 и сообщить нам, какие записи возвращены. Кроме того, сделайте 'select dump (ordertype) из таблицы, где ordertype NOT BETWEEN 'ZAAA' AND 'ZZZZ';' и опубликуйте результат. –

ответ

10
SELECT * FROM table where ordertype <= 'ZAAA' AND ordertype >= 'ZZZZ'; 

строка не может быть < = 'ZAAA' и> = 'ZZZZ'. Вы должны использовать дизъюнкцию вместо:

SELECT * FROM table where ordertype < 'ZAAA' OR ordertype > 'ZZZZ'; 

Кстати, учитывая, что BETWEEN является включительно, NOT BETWEEN является эксклюзивным


Это распространенная ошибка. Вы должны помнить De Morgan's Laws:

not (A and B) таких же, как (not A) or (not B)

Не стесняйтесь экспериментировать с этим простым живым примером, чтобы убедить себя, что эти результаты вполне когерентные: http://sqlfiddle.com/#!4/d41d8/38326


Это, как говорится, единственный способ (я могу видеть) Для строки, как ZOCO для не находится между ZAAA и ZZZZ будет:

  • , имеющие какой-то скрытый характер только за Z (т.е.: 'Z'||CHR(0)||'OCO')
  • или с использованием локалите, такие как Z фактически -Что рассматривать как другую букву, с порядка сортировки за пределами заданного диапазона. Я не знаю, существует ли такая локаль, но, например, в Уэлче, LL рассматривается как одна буква, которую следует сортировать после простой L. См http://en.wikipedia.org/wiki/Alphabetical_order#Language-specific_conventions
  • или имеющие homogplyphs, такие как 0, или О вместо O в ваших данных.
+4

(далекий звук facepalm) 30 лет программирования exp, степень в области информатики, но я не мог это заметить. :-) Ясный признак того, что я истощен. +1 для приятного объяснения. – nop77svk

+0

Привет Sylvain, спасибо за указание - я исправил свой первый запрос - я пытаюсь запросить, где ordertype <'ZAAA' или ordertype> 'ZZZZ'. Сказав это, я не понял комментария относительно закона ДеМоргана. NOT BETWEEN 'ZAAA' AND 'ZZZZ', основанный на вашем комментарии выше, переводится как (NOT ordetype> 'ZAAA') ИЛИ (NOT ordertype <'ZZZZ'). ZOCO предоставит для этого (false) или (false) - поэтому он не должен возвращать ZOCO в результате этого запроса. – user3208146

+0

@ user3208146 Прошу прощения, я не могу сказать вам гораздо больше: если '' ZOCO 'BETWEEN' ZAAA 'AND' ZZZZ'' является _false_, единственные объяснения, которые могли прийти мне на ум, - это те, которые я дал в вторая часть моего ответа.Либо какой-то скрытый символ, либо сортировка с учетом орфографии «ZO» в виде отдельной буквы или гомоглифов. –

2

Ваше понимание того, что оба утверждения одинаковы, неверно. NOT BETWEEN не оценивается так, как вы думаете. Он просто возвращает результаты, которые выходят за рамки оценки BETWEEN для параметров.

Если вы проверить документацию Oracle для МЕЖДУ, он говорит -

The value of 

expr1 NOT BETWEEN expr2 AND expr3 
is the value of the expression 

NOT (expr1 BETWEEN expr2 AND expr3) 
+1

Нет, 'NOT BETWEEN' не должен возвращать все записи. Записи, которые находятся между 'ZAAA' и' ZZZZ' (например, 'ZBCD'), не будут возвращены в обоих операторах. –

+1

Да, вы правы! – Incognito

+0

Спасибо Рене. Итак, в моем примере - ZOCO находится между ZAAA и ZZZZ на основе сортировки символов Oracle, поэтому NOT BETWEEN не должен возвращать ZOCO, правильно? – user3208146

2

Если это не между значениями, оно должно быть либо < OR>, не AND.

2

В первом запросе, вы просите записей, которые в то же время менее 'ZAAA', а также больше, чем 'ZZZZ'. Разумеется, нет такой ценности, которая полностью заполняет оба требования, следовательно, возвращаются нулевые записи.

Во втором запросе, вы спросите для записей, которые либо менее 'ZAAA'или больше 'ZZZZ' (т.е. не между этими границами [not between...]). Существует вероятность того, что такие записи существуют, и, как доказывает ваш запрос select, действительно есть такие записи, которые возвращаются оператором.

+0

Я неправильно написал свой вопрос. Первый запрос должен быть ordertype <'ZAAA' OR ordertype> 'ZZZZ', а второй тип заказа NOT BETWEEN 'ZAAA' AND 'ZZZZ'. – user3208146

Смежные вопросы