Полуоткрытый (или Half-Open, полузакрытый , Half-Bounded ) интервалы ( [a,b)
где x
принадлежит интервалу МФЛ a <= x < b
) довольно распространены в программировании, так как они имеют много удобных свойств.
Может кто-нибудь предложить обоснование, которое объясняет, почему SQL BETWEEN
использует закрытый интервал ( [a,b]
)? Это особенно. неудобно для свиданий. Почему вы так BETWEEN
себя вели?
Ответы:
Я думаю, что инклюзивность
BETWEEN
более интуитивна (и, очевидно, так же, как и дизайнеры SQL), чем полуоткрытый интервал. Например, если я скажу «Выберите число от 1 до 10», большинство людей будут включать числа от 1 до 10. В действительности открытый интервал особенно запутывает не-разработчиков, потому что он асимметричный. Иногда непрограммисты используют SQL для выполнения простых запросов, и полуоткрытая семантика была бы для них гораздо более запутанной.источник
ВОПРОС: Почему SQL между включительно?
ОТВЕТ: Поскольку разработчики языка SQL приняли плохое проектное решение, им не удалось предоставить синтаксис, который позволил бы разработчикам указать, какой из 4 вариантов BETWEEN (закрытый, полуоткрытый левый, полуоткрытый правый или открытый они бы предпочли.
РЕКОМЕНДАЦИЯ: Если / до тех пор, пока не будет изменен стандарт SQL, не используйте МЕЖДУ для дат / времени. Вместо этого приобретите привычку кодировать сравнения диапазона ДАТЫ как независимые условия на начальной и конечной границах вашего диапазона МЕЖДУ. Это немного многословно, но оставит вам написание условий, которые являются интуитивно понятными (а значит, менее подвержены ошибкам) и понятными оптимизаторам базы данных, что позволяет определять оптимальные планы выполнения и использовать индексы.
Например, если ваш запрос принимает спецификацию входного дня и должен вернуть все записи, приходящиеся на эту дату, вы должны кодировать как:
WHERE DATE_FIELD >= :dt AND DATE_FIELD < :dt+1
Попытка написать логику с помощью BETWEEN рискует проблемами с производительностью и / или ошибочным кодом. Три распространенных оплошности:
1)
WHERE DATE_FIELD BETWEEN :dt AND :dt+1
Это почти наверняка ошибка - пользователь ожидает увидеть только записи за определенную дату, но в один прекрасный день будет получен отчет, содержащий записи с 12:00 следующего дня.
2)
WHERE TRUNC(DATE_FIELD) = :dt
Дает правильный ответ, но применение функции к DATE_FIELD сделает большую часть индексации / статистики бесполезной (хотя иногда администраторы баз данных пытаются помочь, добавляя индексы на основе функций к полям даты - по-прежнему сжигая человеко-часы и дисковое пространство и добавляя накладные расходы на IUD операции на столе)
3)
WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60
Том Кайт, экстраординарный гуру Oracle, рекомендует это не слишком элегантное (IMO) решение. Работает отлично, пока вы не потратите весь день на поиск этого «1-1 / 24/06/60» в запросе, который дает неполные результаты ... или пока вы случайно не используете его в поле TIMESTAMP. Плюс, это немного запатентовано; совместим с типом данных Oracle DATE (который отслеживает второй), но должен быть скорректирован с точностью DATE / TIME различных продуктов баз данных.
РЕШЕНИЕ: обратиться в комитет ANSI SQL с просьбой улучшить спецификации языка SQL, изменив синтаксис BETWEEN для поддержки спецификации альтернатив по умолчанию CLOSED / INCLUSIVE. Нечто подобное могло бы сработать:
Подумайте, как легко выразить
WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE
(или простоWHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL
)Может быть, ANSI SQL: 2015?
источник
exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3
что вы можете поддерживать оператор между, чтобы вы знали, что это ранжированный предикат, а предикат неравенства гарантирует его полуоткрытость.И inclusive (
a <= x <= b
), и exclusive (a < x < b
) примерно одинаковы, поэтому при разработке стандартов им просто нужно было выбрать один. «Между» в обычном английском языке обычно включительно, и SQL-выражение предназначено для чтения, похожего на английское предложение, поэтому включение было разумным выбором.источник
a <= x < b
полуоткрыт.Оператор не вызывается
∩[a,b)
, он называетсяBETWEEN
, так что его семантика гораздо более уместна, если использовать его в английской фразе «находится между», чем в математическом предикате «находится в полуоткрытом интервале».источник
BETWEEN
оператор не использует семантику английской фразы «между». В английском языке «между» - это время, пространство или интервал, который разделяет вещи (то есть, он исключает ). Если вы попытаетесь ударить по мячу, мяч должен пройти между стойками, чтобы забить. Если вы нажмете на сообщение, не пройдя между ними - нет очков для вас.