Як ви зберігаєте "нечіткі дати" в базі даних?


125

Це проблема, з якою я стикався кілька разів. Уявіть, що у вас є запис, який ви хочете зберегти в таблиці бази даних. У цій таблиці є стовпець DateTime, який називається "date_create". Цей один конкретний запис був створений давно, і ви не дуже впевнені в точній даті, але ви знаєте рік і місяць. Інші записи ви знаєте лише рік. Інші записи ви знаєте день, місяць та рік.

Ви не можете використовувати поле DateTime, оскільки "травень 1978 року" не є дійсною датою. Якщо розділити його на кілька стовпців, ви втратите можливість запиту. Хтось ще наткнувся на це, якщо так, як ви впоралися?

Для уточнення системи, яку я будую, це система, яка відстежує архіви. Деякий контент був створений дуже давно, і все, що ми знаємо, - "травень 1978 року". Я міг би зберігати його як 1 травня 1978 року, але лише певним чином позначити, що ця дата точна лише до місяця. Таким чином, через кілька років, коли я переглядаю цей архів, я не плутаюся, коли дати не збігаються.

Для моїх цілей важливо розмежувати "невідомий день у травні 1978 року" з "1 травня 1978 року". Крім того, я не хотів би зберігати невідомі як 0, як "0 травня 1978 року", оскільки більшість систем баз даних буде відкидати це як недійсне значення дати.


14
Чи важливо відрізняти "невідомий день у травні 1978 року" від "1 травня 1978 року"?

5
@MichaelT: так, важливо диференціювати.
nbv4


6
@aslum: Більшість систем бази даних відкине це як недійсне значення дати
nbv4

9
@JimmyHoffa - ти ніколи не стикався з нечіткими сценаріями побачень або з тим, де тобі потрібно було порівняти дати? В будь-якому випадку звичайним є історія хвороби: ви пам’ятаєте, що апендектомія була минулого року 1 квітня, але тонзилектомія була колись у 1975 році, а щось трапилося ще в травні та червні якогось року. Що робити, якщо ви хочете дізнатися, чи була якась медична подія до або після якогось іншого медичного прориву? Це сталося до або після того, як вони перевіряли запаси крові на ВІЛ?
четверггек

Відповіді:


148

Зберігайте всі дати у звичайному полі DATE в базі даних та вкажіть додаткове поле точності наскільки точним є поле DATE.

date_created DATE,
date_created_accuracy INTEGER, 

date_create_accuracy: 1 = точна дата, 2 = місяць, 3 = рік.

Якщо ваша дата нечітка (наприклад, травень 1980 року), зберігайте її на початку періоду (наприклад, 1 травня 1980 р.). Або якщо ваша дата точна до року (наприклад, 1980), зберігайте її як 1 січня. 1980 з відповідним значенням точності.

Цей спосіб може легко запитувати дещо природним шляхом і все ще не мати поняття, наскільки точні дати. Наприклад, це дозволяє запитувати дати між Jan 1st 1980і Feb 28th 1981, а також отримувати нечіткі дати 1980та May 1980.


1
Ви все ще повинні обчислити дату закінчення з того, що я бачу, тому я вважаю, що між запитом досить некрасиво, оскільки у вас в кращому випадку ви маєте обчислене поле, яке ви вибираєте.
Wyatt Barnett

8
Гарна відповідь, дійсно розумна. select * from mytable where date_created between "1980/1/1" and "1981/2/28" and date_created_accuracy <= 2;. Геніальність.
Naftuli Kay

58
Я б закликав вас вважати точність дати просто "днями". Якщо точний день дорівнює 0. Таким чином, можна використовувати більш гнучкі дати "Колись влітку" з точністю дати 90 днів, починаючи з 1 червня, а не з жорстким кодуванням конкретних діапазонів дат. Він також міг би обробляти багаторічну точність.

1
Можливо, ви можете надіслати це як відповідь, MichaelT
Supr

1
+1: Ще одна приємна річ у цьому рішенні - ви можете додати логіку відображення на основі значення date_created_accuracyполя. Ви можете показати "травень 1980" або просто "1980" в результатах чи інтерфейсі користувача, якщо це так точно, як вказує поле.
Kyralessa

27

Якщо вам не потрібно використовувати подібний тип даних як звичайну інформацію про дату, час, будь-який простий формат рядка, буде.

Але якщо вам потрібно зберегти весь функціонал, я можу придумати два обхідні шляхи, які вимагають додаткової інформації, що зберігається в базі даних:

  1. Створіть min dateі max dateполя, які мають різні значення для "неповних" даних, але збігатимуться для точних дат.
  2. Створіть типи для кожного виду неточної дати (None _ 0, date_missing _ 1, month_missing _ 2, year_missing_4 тощо тощо, щоб ви могли їх поєднувати). Додайте typeполе до записів і збережіть, яка інформація відсутня.

Поля мінімальної та максимальної дати також були моєю першою думкою.
Майкл Іцо

1
Довгий запуск назад нам довелося вирішити саме таку проблему. Користувачі могли розповідати історії про події, що сталися будь-коли в минулому, тому нам довелося підтримувати нечіткі дати. Після довгого повернення назад рішення, до якого ми дійшли, найбільше схоже на пропозицію superM тут, де дати зберігаються як мінімальні та максимальні можливі моменти, які містили б дату історії. Коли повідомляється про дату, точність (тобто "цей запис точний місяцю / році / дня") може бути витягнута з дельти між датами min та max. Не потрібно зберігати 3-те поле для точності.
meetamit

4
+1 для min dateта max dateполя. Я думаю, що це найбільш гнучке, але точне та просте у використанні рішення.
Супр

1
Я спочатку був антагоністичним до цієї ідеї. Але розуміючи, що це найбільш гнучкий підхід, я голосую за це.
Анураг Калія

Це лише природно. Ви описуєте не стільки нечітку дату, скільки часовий проміжок ..... який має початок і кінець.
Пітер Б

20

Це насправді більше визначення вимог, ніж технічна проблема - на що потрібно зосередитися, "як ми можемо визначити дати в минулому", і технічне рішення буде текти.

Часи, коли мені доводилося наближатися до чогось подібного, ми зазвичай:

  • Визначте, як відображати речі - як пропонує MichaelT , вирішіть, що все, що визначається як місяць / день, визначається як півночі першого місяця. Це, як правило, досить добре для більшості цілей - якби точна дата була такою важливою, ви, мабуть, мали б запис про це через 35 років, правда?
  • З'ясуйте, чи потрібно це відслідковувати - IE, чи потрібні записи із трохи складеними датами, щоб прапор сказав так? Або це лише проблема навчання користувачів, тому люди знають і можуть діяти відповідно.

Іноді потрібно зробити щось на кшталт зробити дати нечіткими - наприклад, для однієї дати може знадобитися відповідь на запит про що-небудь у травні 1978 року. Це можливо - просто зробіть ваші поля create_date 2, а старі записи отримають 30 днів поширюються у відповідних випадках, нові отримують 2 однакових значення.


1
+1 - Я працював над формулюванням відповіді з підходом на подвійну дату. Свою відповідь ви отримали першими.

2
+1, це некрасиво і створює безліч непотрібної додаткової інформації для нових записів, які цього не потребують, але, з іншого боку, це робить запити набагато простішими, ніж вони були б інакше. Ми вже деякий час використовуємо подібне рішення для пов’язаної проблеми.
Ізката

3
@Izkata - Справедливий момент, але наскільки витонченим ви можете отримати, коли вам потрібно зробити щось, що повинно бути єдиним моментом за місяць. Звичайно, красивіше, ніж десь обчислювати початок і кінець для запитів.
Wyatt Barnett

1
+1 за можливість позначати довільну деталізацію без вибуху значень enum.
Dan Neely

18

Найпростіший спосіб позначити, чи точно вказана дата - це створити поле точності INT (1) з NULL за замовчуванням

Якщо дата є точною, зберігайте дату та час у "date_create" та залишайте точність NULL

Якщо дата точна до дати зберігання дати місяця як 1 числа місяця із значенням точності 1

Якщо дата точна лише для року, дата зберігання 1 січня із значенням точності 2

Ви можете використовувати різні числа для зберігання різних значень, таких як перша чверть тощо


Коли ви робите це, запити стають дійсно волохатими.
Blrfl

3
У цьому виникають труднощі з даними, які не мають меж чистого місяця, таких як "Q2 1991" та "Winter 1978-1979".

1
ОП хоче певним чином позначити, що ця дата точна лише до місяця.
david strachan

7
Ви тут зловживаєте значенням NULL. NULL означає "невідомо", тому якщо дата точна, точність не може бути NULL. Це може бути "1".
Конерак

@Konerak Семантично так. Але оскільки більшість дат є точними, потрібно визначити лише окремі випадки та використовувати тут NULL як за замовчуванням.
Давид страчан

17

Раніше я зберігав дати з точністю як дату початку, так і кінцеву дату. День травень21,2012 року буде представлений як початок = 12 ранку, травень21,2012 р. І кінець = 12 ранку, травень22,2012 р. 2012 рік буде представлений як початок = 12 ранку, Ян1,2012 кінець = 12 ранку, Ян1,2013.

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

Однак, коли ви не намагаєтесь перекласти на людину, програмувати з кінцевими точками набагато простіше, ніж з точністю + центр. Ви не закінчите безліч справ. Це дуже приємно.


Насправді, не потрібно бути таким складним, щоб визначити, як подати діапазон, якщо діапазон завжди зберігається як UTC. Як часові позначки UTC, кожен день, тиждень, місяць, рік - навіть сезони та квартали - матимуть два постійних, глобальних, чітких та легко визначених числа, що представляють початок та кінець періоду. Логіка просто стає декількома твердженнями if, щоб побачити, чи є дві дати на початку та в кінці певного періоду. Ніяких складних матеріалів з математики чи часового поясу не потрібно :)
Supr

@Supr Визначення того, чи є певна секунда на кордоні певного періоду людини, саме по собі є складною проблемою. Особливо в довгостроковій перспективі, коли обертання Землі сповільнюється і не змінюються невеликі зміни людського визначення місцевого часу.
Крейг Гідні

14

Чому б не зберігати дві дати.

Створено_Після і Створено_Перед. Фактична семантика, що "створюється на або після" та "створюється на або раніше"

Тож якщо ви знаєте точну дату, тоді Created_After і Created_Before будуть тією ж датою.

Якщо ви знаєте, що це був перший тиждень у травні 2000 року, тоді Created_After = '2000-05-01' та Created_Before = '2000-05-07'.

Якщо ви просто знаєте травень 1999 року, то значення будуть "1999-05-01" та "1999-05-30".

Якщо це "Літо 42 року", то значення будуть "1942-06-01" та "1942-08-31".

Ця схема проста в запиті за допомогою звичайного SQL і досить проста для не технічного користувача.

Наприклад, щоб знайти всі документи, які могли бути створені в травні 2001 року:

SELECT * FROM DOCTAB WHERE Created_After < '2001-05-31' And Created_Before > 2001-05-01;

І навпаки, щоб знайти усі документи, які були визначені в травні 2001 року:

SELECT * FROM DOCTAB WHERE Created_After > '2001-05-01' And Created_Before < 2001-05-31;

1
Я думаю, що це найелегантніше рішення.
Пітер Б

Це те саме, що відповіді superM та Strilanc. +1, хоча для більш чіткого пояснення та показу, наскільки простий буде запит.
Супр

9

Формат часу ISO 8601 поставляється з визначенням тривалості, наприклад

2012-01-01P1M (читайте: 2012, 1 січня, період: 1 місяць) - це те, що повинно бути «у січні 2012 року».

Я б використовував це для зберігання даних. Для цього вам може знадобитися поле бази даних типу String. Це інша тема, як провести розумний пошук з цього приводу.


+1 за ідею, але -1 за те, що не використовується поле дати з причини пошуку та / або пошуку
user151019

Залежить від бази даних. Однак це може бути підґрунтям для розширення, але питання полягає в тому: чи документ у результатах встановлений, якщо ви шукаєте, в цьому випадку, всі документи новіші, ніж 12 січня, чи ні? Це не банально. Тут було питання, як зберігати нечіткі дати.
Маттіас Ронге

3

Як правило, я все ще зберігаю їх як дати до загального замовлення запитів, як і раніше, навіть якщо трохи менш точні.

Якщо важливо знати точність, яку я мав у минулому, або зберігалося "вікно" точності або як +/- десятичний, або як пошук (день, місяць, рік тощо). В інших випадках замість вікна я просто зберігаю початкове значення дати у вигляді рядка і конвертую те, що я можу, у дату, можливо, 1978-05-01 00:00:00 та "травень 1978" для даного прикладу.


3

Якщо розділити його на кілька стовпців, ви втратите можливість запиту.

Хто каже? Ось що ви робите:

  1. Майте 3 стовпчики, день, місяць, рік, кожен із типів int та четвертий стовпець TheDate типу DateTime.
  2. Майте тригер, який використовує 3 стовпці День, Місяць, Рік для складання TheDate, якщо TheDate залишено нульовим, але одне або кілька полів День, Місяць, Рік має значення.
  3. Майте тригер, який заповнює поля "День", "Місяць", "Рік", коли надається TheDate, але ці поля - ні.

Тож якщо я вставлю вкладку на кшталт: insert into thistable (Day, Month, Year) values (-1, 2, 2012);тоді TheDate стане 2/1/2013, але я дізнаюся її дійсно невизначену дату в 2/2012 через -1 в полі «День».

Якщо у мене insert into thistable (TheDate) values ('2/5/2012');тоді День буде 5, Місяць буде 2, а рік - 2012, і оскільки жоден з них не -1, я знаю, що це точна дата.

Я не втрачаю можливості запиту, оскільки тригер вставки / оновлення гарантує, що мої 3 поля (день, місяць, рік) завжди створюють у TheDate значення DateTime, яке можна запитувати.


3

Іншим варіантом буде збереження дат як цілих чисел форми YYYYMMDD.

  • Ви знаєте лише рік 1951: Зберігайте як 19510000
  • Ви знаєте, що місяць і рік - березень 1951 року: Зберігайте як 19510300
  • Ви знаєте, повна дата - 14 березня 1951 року: Зберігати як 19510314
  • Зовсім невідома дата: зберігати як 0

Переваги

Ви можете зберігати свою нечітку дату в одному полі замість двох полів дати або дати та точності, як підказує багато інших відповідей.

Запити все ще прості:

  • всі записи за 1951 рік - SELECT * FROM table WHERE thedate>=19510000 and thedate<19520000
  • всі записи за березень 1951 р. - SELECT * FROM table where thedate>=19510300 and thedate<19510400
  • усі записи за 14 березня 1951 р. - SELECT * FROM table where thedate=19510314

ПРИМІТКИ

  • Вашому графічному інтерфейсу знадобиться GetDateString(int fuzzyDate)який досить просто здійснити.
  • Сортування легко за допомогою формату int. Ви повинні знати, що невідомі дати прийдуть першими. Ви можете змінити це за допомогою 99"прокладки" замість 00місяця чи дня.

Як ви представляєте нечітку дату "зими 1941-1942 років"? Це може бути грудень 1941 року або січень 1942 р.

1
Ваше запитання пов'язане із загальним випадком вирішення. Оригінальне запитання не перераховує це як проблему. Виходячи з розміщеного питання, іноді відома повна дата, колись лише рік і місяць, а іноді лише рік. Жодне питання нечіткого діапазону дат не згадується як вимога. Я погоджуюся, що вам потрібно вирішити дві дати, якщо вам потрібно вирішити цю проблему (хоча, зберігання діапазону як два "нечіткі вставки дати" може забезпечити більшу гнучкість, ніж зберігання двох "жорстких" дат).
Рік

1

ISO 8601 також визначає синтаксис "нечітких дат". 12 лютого 2012 року о 15:00 буде "2012-02-12T15", а лютий 2012 року може бути просто "2012-02". Це добре поширюється, використовуючи стандартне лексикографічне сортування:

$ (echo "2013-03"; echo "2013-03"; echo "2012-02-12T15"; echo "2012-02"; echo "2011") | sort
2011
2012
2012-02
2012-02-12T15
2013-03

0

Ось мій погляд на це:

Перехід від нечіткої дати до об'єкта datetime (який впишеться в базу даних)

import datetime
import iso8601

def fuzzy_to_datetime(fuzzy):
    flen = len(fuzzy)
    if flen == 4 and fuzzy.isdigit():
        dt = datetime.datetime(year=int(fuzzy), month=1, day=1, microsecond=111111)

    elif flen == 7:
        y, m = fuzzy.split('-')
        dt = datetime.datetime(year=int(y), month=int(m), day=1, microsecond=222222)

    elif flen == 10:
        y, m, d = fuzzy.split('-')
        dt = datetime.datetime(year=int(y), month=int(m), day=int(d), microsecond=333333)

    elif flen >= 19:
        dt = iso8601.parse_date(fuzzy)

    else:
        raise ValueError("Unable to parse fuzzy date: %s" % fuzzy)

    return dt

Потім функція, яка приймає об'єкт datetime, і переміщує його назад у нечітку дату.

def datetime_to_fuzzy(dt):
    ms = str(dt.microsecond)
    flag1 = ms == '111111'
    flag2 = ms == '222222'
    flag3 = ms == '333333'

    is_first = dt.day == 1
    is_jan1 = dt.month == 1 and is_first

    if flag1 and is_jan1:
        return str(dt.year)

    if flag2 and is_first:
        return dt.strftime("%Y-%m")

    if flag3:
        return dt.strftime("%Y-%m-%d")

    return dt.isoformat()

А потім одиничне випробування. Я пропустив якісь випадки?

if __name__ == '__main__':
    assert fuzzy_to_datetime('2001').isoformat() == '2001-01-01T00:00:00.111111'
    assert fuzzy_to_datetime('1981-05').isoformat() == '1981-05-01T00:00:00.222222'
    assert fuzzy_to_datetime('2012-02-04').isoformat() == '2012-02-04T00:00:00.333333'
    assert fuzzy_to_datetime('2010-11-11T03:12:03Z').isoformat() == '2010-11-11T03:12:03+00:00'

    exact = datetime.datetime(year=2001, month=1, day=1, microsecond=231)
    assert datetime_to_fuzzy(exact) == exact.isoformat()

    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=1, day=1, microsecond=111111)) == '2001'
    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=3, day=1, microsecond=222222)) == '2001-03'
    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=6, day=6, microsecond=333333)) == '2001-06-06'

    assert datetime_to_fuzzy(fuzzy_to_datetime('2002')) == '2002'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2002-05')) == '2002-05'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2002-02-13')) == '2002-02-13'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2010-11-11T03:12:03.293856+00:00')) == '2010-11-11T03:12:03.293856+00:00'

Існує кутовий випадок, коли подія, яка саме відбулася, 2001-01-01T00:00:00.333333але система трактує як "2001", але це здається дуже малоймовірним.


0

Я працюю у видавничій компанії, яка займається багатьма старими книгами, де ми часто не можемо отримати точні дати для речей. Як правило , ми маємо два поля для даного запису дати, дати і ок булеві:

date date
dateCirca enum('Y', 'N')

Ми використовуємо поле дати для позначення дати якоїсь події або дати, яка є "достатньо близькою" у випадку, коли ми не знаємо справжню дату. У випадку, якщо ми не знаємо справжню дату, ми позначаємо dateCircaполе як Yі даємо достатньо близьку дату, яка позначається як "перша", наприклад

1st March, 2013  // We don't know the day of the month
1st January, 2013  // We don't know the month/day of the year
1st January, 2000  // We don't know the month/day/year, we only know the century

0

Огляд

Для зберігання нечітких дат (або навіть просто нечітких дат) існує багато можливих уявлень і, таким чином, схем баз даних:

  1. Дата та час та код, що вказує на його точність чи точність
  2. Дата та час та інтервал, коли існує кілька можливостей представлення інтервалу:
    1. Представити всі інтервали у вигляді цілої (або іншої числової) кількості певної фіксованої одиниці, наприклад, днів, хвилин, наносекунд.
    2. Представити інтервал як цілою (або іншою числовою) величиною, так і кодом із зазначенням його одиниць.
  3. Час початку та закінчення дати
  4. Рядок
  5. Розподіл ймовірностей:
    1. Десяткові або величини з плаваючою комою для параметрів, які задають конкретний розподіл у певній родині, наприклад, середнє та стандартне відхилення нормального розподілу.
    2. Функція розподілу ймовірностей, наприклад, як (пошук) коду (можливо, з параметрами конкретних значень) або як вираз у достатньо виразній мові, форматі чи поданні.

[1], [2] і [3] - це всі (неявно) рівномірні інтервали, тобто сукупність (однаково) можливих моментів часу.

[4] є найбільш експресивним, тобто дозволяючи будь-які можливі (або принаймні довільно довгі) письмові мовні пропозиції або фрази. Але з цим також найважче працювати. В межах межі, для обміну довільними значеннями потрібно буде ШІ на рівні людини. Практично діапазон можливих значень повинен бути суворо обмежений, а альтернативні «структуровані» значення, ймовірно, будуть бажані для багатьох операцій, наприклад, сортування, пошук.

[5] - це, мабуть, найбільш загальне компактне зображення, яке (дещо) практично.

Уніфіковані інтервали

Уніфіковані інтервали - це найпростіший компактний спосіб представити набір (можливих) значень дати та часу.

Для [1] ігноруються частини значення дати-часу, тобто частини, що відповідають одиницям, більш точним, ніж зазначена точність або точність; в іншому випадку це еквівалентно [2], а код точності / точності еквівалентний інтервалу з тими ж одиницями (і мається на увазі кількість 1).

[2] та [3] виразно еквівалентні. [1] суворо менш виразний, ніж будь-який, оскільки існують ефективні інтервали, які неможливо представити [1], напр. нечіткий час-дату, еквівалентний 12-годинному інтервалу, який охоплює межу дати.

[1] користувачам легше вводити дані, ніж будь-яке інше представлення, і, як правило, потрібно вимагати (принаймні трохи) менше вводити текст. Якщо дати можна вводити в різних текстових поданнях, наприклад, "2013", "2014-3", "2015-5-2", "30.07.2016 11p", "2016-07-31 18:15" , точність або точність також можна автоматично виводити з вхідних даних.

Точність або точність [1] також найпростіше перетворити у форму, яку слід передати користувачам, наприклад, "2015-5 з місячною точністю" до "травня 2015", порівняно з "13 травня 2015 2p, плюс або мінус 13,5 днів" (тому зауважте, що останній не може бути представлений [1] у будь-якому випадку).

Струни

Практично, рядкові значення потрібно буде перетворити на інші представлення для запиту, сортування чи порівняння численних значень. Отже, хоча будь-яка письмова природна (людська) мова є строго виразнішою, ніж [1], [2], [3] або [5], ми ще не маємо засобів для обробки набагато поза стандартними текстовими поданнями або форматами. Враховуючи це, це, мабуть, найменш корисне представлення саме по собі .

Однією з переваг цього представлення є те, що значення на практиці повинні бути представлені користувачам такими, які є, і не вимагати, щоб трансформація була легко зрозумілою.

Імовірні розподіли

Розподіли ймовірностей узагальнюють рівномірні інтервальні подання [1], [2], [3] та (можливо) є еквівалентними (загальним) поданням рядків [4].

Однією з переваг розподілу ймовірностей над рядками є те, що перша є однозначною.

[5-1] було б доречно значення, які (здебільшого) відповідають існуючому розподілу, наприклад, значення часу-дати, що виводиться з пристрою, для якого відомо вимірювання (або вважається), що відповідає певному розподілу.

[5-2], мабуть, найкращий (дещо) практичний спосіб компактно представити довільні значення "нечітких дат". Звичайно, обчислення конкретних розподілів ймовірностей, що використовуються, є певні цікаві (і, можливо, неможливі) проблеми, які слід вирішити під час запитів, сортування чи порівняння різних значень, але багато цього, мабуть, уже відомо або вирішено десь у існуючих математичної та статистичної літератури, тому це безумовно виступає як надзвичайно загальне та неоднозначне уявлення.


-1

Мені дуже подобається рішення Джеймса Андерсона - Точне обмеження дат - це спосіб отримати найбільш гнучку структуру запитів. Ще один спосіб досягти того ж - використовувати стартовий, кінцевий або навіть центр dateплюс плюс interval(доступний принаймні в PostgreSQL , Oracle та SQLAlchemy ).


-2

У вашому випадку вам потрібні лише рік, місяць і день. Рік і місяць обов'язкові, день необов’язковий. Я б використав щось подібне:

year smallint not null,
month smallint not null,
day smallint

Плюс в тому, що ви все ще можете дуже ефективно використовувати індекси. (Мініатюрні = мінуси, черги стають трохи "складнішими" (довше).


1
Але це означає, що якщо нечіткість також піднімає частину місяця, такий підхід не вдається.
Анураг Калія

1
@AnuragKalia - так зробіть поле місяця нульовим. Ні з якої причини це не вдалося перенастроїти на більш пізній час.
JeffO

Це був лише приклад. Рішення повинно бути достатньо загальним для вирішення майбутніх проблем. Якщо діапазон, який ви вказуєте, становить 15 березня 2013 р. По 22 березня 2013 р., Цей підхід не працює. Мінімальна відповідь, подана вище, є найбільш загальною поки що.
Анураг Калія

1
Чи знайшли ви таку вимогу на посаді в ОП або це лише ваша фантазія?
Дунайський матрос

Зміна місячного нуля дозволяє вказати день, а не місяць. Не має сенсу. Коли було 1978-??-31?
MSalters

-2

Я б просто зберігав точний час для звичайних дат і зробив частину часу нечіткої дати загальною, як 00:00:00. Тоді я зробив би всі нечіткі дати 1-го місяця.

Коли ви запитуєте, ви

  1. перевірка діапазонів дат, коли час також дорівнює 00:00:00 (нечіткий)
  2. перевірка діапазонів дат, коли час НЕ дорівнює 00:00:00 (реально)
  3. перевірити діапазони дат, але ігнорувати частину часу (комбіновано)

Є кращі рішення, ніж це, але я особисто ненавиджу метадані (дані про мої дані). Просто має звичку через деякий час виходити з рук.


2
як би ця справа з реальною датою встигла 00:00:00?
гнат

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