Чому SQL BETWEEN включений, а не напіввідкритий?


45

Напіввідкритий (або Half-Open, напівзакритий , Half-Bounded ) інтервали ( [a,b)де xналежить інтервалу МФЛ a <= x < b) досить поширені в програмуванні, так як вони мають багато зручних властивостей.

Чи може хтось запропонувати обґрунтування, яке пояснює, чому SQL BETWEENвикористовує закритий інтервал ( [a,b])? Це esp. незручний для побачень. Чому б ти BETWEENповодився так?


Мені цікаво, якими зручними властивостями вони володіють?
phant0m

2
якби це не було включно, як ви могли легко запросити всі прізвища в діапазоні від A до D? або називає W до Z? Для чисел від 1 до 10 ви можете шукати 0 <n <11, але для символів вам доведеться використовувати ASCII числа? або unicode числа? Плюс до цього, індекси можуть легко привести вас до початку даних.
jqa

2
Я розумію ваше розчарування (StartDate> = '2010-01-01' та StartDate <'2011-01-01'), прекрасно працює, використовувати між Еквівалентним було б (StartDate між '2010-01-01' та ' 2010-12-31 23:59:59 '), і громіздкі, і потрібно знати, скільки днів у грудні
Тодд

1
@ phant0m [a, b) U [c, d) == [a, d). [a: int, b: int) містить точно елементи ba. Коментар Тодда показує, як вони особливо добре працюють на побачення (що я найбільше сумую за ними). В основному, при кодуванні напіввідкриті інтервали, як правило, простіші, простіші у використанні та надійні.
alex

Найкраща відповідь повинна містити посилання на об'єктивну документацію рішення від людей, які вперше вказали МІЖ для SQL, тим самим відповівши чому, а не обрану суб'єктивну відповідь.
Тодд

Відповіді:


48

Я думаю, що включення BETWEENє більш інтуїтивним (і, мабуть, так зробили дизайнери SQL), ніж напіввідкритий інтервал. Наприклад, якщо я скажу "Виберіть число від 1 до 10", більшість людей включить числа 1 і 10. Відкритий інтервал насправді особливо заплутаний для не розробників, оскільки він несиметричний. SQL іноді використовується непрограмістами для створення простих запитів, і напіввідкрита семантика була б для них набагато заплутанішою.


9
Ваш приклад зосереджується на цілих числах, для десяткових чисел та інших обмежених кількостей (таких як дати), термін між ними неоднозначний. Якщо я скажу, що ви зробили Х між 2012 та 2013 роками, я не включаю 2013 (або конкретно день 2013-01-01)
Тодд

4
@Todd Будь-яке використання цих термінів неоднозначне. Ось чому математики, вчені та кмітливі програмісти документують свої наміри як «напіввідкриті» чи такі. Я думаю, що відповідь Олеського полягає в тому, що SQL спочатку був призначений для кінцевих користувачів, а не програмістів (справді!). Мабуть, дизайнери SQL вирішили визначити, що вони вважають найкращим для цієї аудиторії. Але, як вважають автори Питання, напіввідкритий майже завжди кращий для роботи з діапазонами, такими як проміжок часу.
Василь Бурк

"Я думаю, що інклюзивність МІЖ інтуїтивніша" є суб'єктивною. "SQL час від часу використовується непрограмістами для створення простих запитів" - Непрограмістам однаково потрібно було б перевірити специфікацію.
Тодд


Також часто задають питання "Виберіть число від 1 до 10" (просто щоб уникнути явної неоднозначності). Як бічна записка. Ви кажете "вибрати число від 1 до 10"; більшість людей, мабуть, не обирають 1 або 10. Зрозуміло, це більше питання психології. :) Люди все одно сприймуть 1 і 10 як вірний вибір (незважаючи на те, що вони семантично неправильні); але це результат контекстуального тлумачення, припускаючи, що 1 і 10 є дійсними. Якби ви сказали: "між 13 і 24", і ви швидше запитаєте, чи включено 13 і 24.
Розчарований

26

ЗАПИТАННЯ: Чому SQL в МІЖ включено?

ВІДПОВІДЬ: Оскільки дизайнери мови SQL прийняли неякісне дизайнерське рішення, оскільки вони не змогли надати синтаксис, який дозволить розробникам вказати, який із 4 варіантів BETWEEN (закритий, напіввідкритий-лівий, напіввідкритий-правий чи відкритий ) вони вважають за краще.

РЕКОМЕНДАЦІЯ: Якщо / до внесення змін до стандарту SQL, не використовуйте МЕЖДУ для дати / часу. Натомість увійдіть у звичку кодувати порівняння діапазону DATE як незалежні умови на початковій та кінці меж діапазону BETWEEN. Це трохи детально, але це дозволить вам створити інтуїтивно зрозумілі умови (таким чином менше шансів на помилку) та зрозумілі для оптимізаторів бази даних, що дозволить визначити оптимальні плани виконання та використовувати індекси.

Наприклад, якщо ваш запит приймає специфікацію дня введення і повинен повертати всі записи, які потрапили на цю дату, ви кодуєте:

  • 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 зробить більшу частину індексації / статистикою марною (хоча іноді DBA намагатимуться допомогти, додавши індекси, засновані на функціях, до полів дати - все ще спалюючи людино-години та дисковий простір та додаючи накладні витрати на IUD операції на столі)

3) WHERE EVENT_DATE BETWEEN :dt AND :dt + 1-1/24/60/60

Том Кіт, додатковий колектив гуру Oracle, рекомендує це не менш елегантне рішення (IMO). Працює чудово, поки ви не витрачаєте цілий день, щоб знайти той "1-1 / 24/06/60" у запиті, який дає неповні результати ... або поки ви випадково не використаєте його в полі TIMESTAMP. Плюс, це трохи фірмові; сумісний з типом даних DATE від Oracle (який відстежує до другого), але його потрібно пристосувати до точності DATE / TIME для різних продуктів бази даних.

РЕШЕННЯ: Запросити комітет ANSI SQL для покращення специфікацій мови SQL, змінивши синтаксис BETWEEN для підтримки специфікації альтернатив за замовчуванням CLOSED / INCLUSIVE. Щось подібне зробило б трюк:

вираження1 МІЖ expr2 [ ВКЛ [USIVE] | EXCL [USIVE]] І expr3 [ INCL [USIVE] | EXCL [USIVE]]

Поміркуйте, як легко висловитись WHERE DATE_FIELD BETWEEN :dt INCLUSIVE AND :dt+1 EXCLUSIVE(або просто WHERE DATE_FIELD BETWEEN :dt AND :dt+1 EXCL)

Можливо ANSI SQL: 2015?


Ця відповідь є порадою мудреця.
Василь Бурк

@KevinKirkPatrick - Чудова відповідь! Я пропоную вам також спробувати знайти документацію рішення як об’єктивне доказ оригіналу Чому.
Тодд

3
Мені особисто подобається, exp1 BETWEEN exp2 AND exp3 AND exp1 != exp3що ти можеш зберігати між оператором, щоб ти знав, що це предикативний діапазон, а предикат нерівності забезпечує напіввідкритість.
Sentinel

@Sentinel, приємно! Я не збираюсь оголошувати себе перетворювачем достроково, але я обов'язково буду пам’ятати цей варіант, коли я буду наступним кодом умов діапазону дат. Спочатку рум'яна має більшу мовну привабливість, ніж exp1> = exp2 AND exp1 <exp3; і, очевидно, однаково добре вирішує проблеми з МЕЖДУ. Мені буде цікаво, якщо якісь оптимізатори виявляють більше «розуміння» однієї варіації над іншою; безумовно, здається правдоподібним, що і ваш може дати кращі результати в цьому плані (хоча, чесно кажучи, я був би дуже розчарований в оптимізаторі, який ставився до них по-різному)
KevinKirkpatrick

@KevinKirkpatrick Я ніколи не переглядав їх, щоб з'ясувати, чи є якісь відмінності, і я також був би розчарований, якби вони були.
Sentinel

8

І включно ( a <= x <= b), і ексклюзив ( a < x < b) приблизно однаково поширені, тому при складанні стандартів їх просто потрібно було вибрати. "Між" в загальній англійській мові, як правило, є інклюзивним, а SQL-вираз призначений для читання, подібного до англійського речення, тому інклюзивний вибір був розумним вибором.


4
Насправді використання англійською мовою ще більше змішане, оскільки ви залишили напіввідкритим. Коли ми кажемо, що "обід - між полуднем і 13:00", ми маємо на увазі напіввідкрите, оскільки вас очікують повернутись на уроці / роботі в момент 13: 00: 00.000, перерва триватиме до першого моменту, але не враховуючи годинна година. a <= x < bє напіввідкритим.
Василь Бурк

1
@BasilBourque: Це може бути пов’язано з нескінченною точністю - наприклад, обід - між полуднем та 12: 59: 99.9999999999999 ....
Брендан

@Brendan Так, ви висловлюєте мою думку. Нескінченна (або неоднозначна) точність - одна з проблем, з якою вирішується використання напіввідкритого підходу до визначення проміжку часу. Сенс у тому, що в англійській розмові ми інтуїтивно обробляємо відкриті та закриті (як згадується у цій відповіді), а також напіввідкриті діапазони без особливої ​​думки. Кожен підхід служить цілі. Ось чому визначення SQL BETWEEN є менш ніж оптимальним. В ідеалі SQL слідкував за пропозицією KevinKirkpatrick .
Василь Бурк

2
SQL повинен бути схожим на англійську мову, і хоча інклюзивне та ексклюзивне може бути однаково поширеним, це мова запитів для аналітиків та програмістів. Як програміст, я думаю, що це визначено неправильно, але це насправді не має значення, я просто уникаю використання "МІЖ". Не велике діло.
Тодд

5

Оператор не називається ∩[a,b), він називається BETWEEN, тому значно більш доречно для його семантики бути англійською фразою "є між", ніж ті, що з математичного предиката "знаходиться в напіввідкритому інтервалі".


Потрібно враховувати всі програми, а не лише англійські програми для наборів Integer. "між 1 і 10", "між полуднем і 13:00", "між 1,0 і 5,0" (грами). "між 5,50 і 10,30" (долари). Неперервні кількості логічно (англійською) вважатимуться виключними.
Тодд

1
Проблема полягає в тому, що BETWEENоператор не використовує семантику англійської фрази "is between". Англійською мовою "між" - це час, простір або інтервал, який розділяє речі (тобто це виключно ). Якщо ви намагаєтесь ударити по воротах, м'яч повинен пройти між повідомленнями, щоб забити. Якщо ви потрапили в пост, не проходячи між ними - для вас не буде рахунку.
Розчарований

1
@CraigYoung, як підказує прийнята відповідь (і я згоден), "якщо я скажу" Виберіть число від 1 до 10 ", більшість людей включать числа 1 і 10 [у свій діапазон можливих відповідей]". У просторовій області я згоден з вами, але для цифр я б сказав, що це інакше. Краще для англійської мови та використання, ніж тут, хоча!
AakashM

@AakashM Моя думка полягає в тому, що ви заявляли про англійську мову, яка є просто хибною за словниковим визначенням слова "між", щоб виправдати семантику програмування. Той факт, що існує загальне розуміння фрази "між 1 і 10", має менший зміст зі значенням "між" і більше стосується позицій 1 і 10, що містяться в системі десяткових чисел. "Автокорекція" людського мозку ігнорує, що "між" виключає в цьому випадку кінцеві точки, тому що здається смішним означати "від 2 до 9". Спробуйте те ж саме з "між 13 і 24". Або навіть "між 0 і 11".
Розчарувались

Між вами та мною категоричні претензії щодо природних мов зазвичай небезпечні.
AakashM
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.