Лучший способ сохранить только день и месяц в базе данных - PullRequest
10 голосов
/ 25 июня 2009

Мы должны сохранить день и месяц ежегодного повторяющегося события. (Думайте об этом как о том году, когда счет должен быть отправлен клиенту.)

Мы должны сделать некоторые вычисления с этой информацией. Например, если клиент платит дважды в год. Тогда мы должны не только проверить, наступил ли сегодня этот день, но также и наступить ли этот день через 6 месяцев.

Теперь у нас есть несколько вариантов: а) Мы сохраняем информацию в поле ДАТА, но игнорируем год. б) Создаем два поля int в базе данных date_day и date_month. c) Мы создаем поле varchar, а затем выполняем регулярное выражение и разделяем, например, 31,12 каждый раз, когда мы делаем некоторые вычисления.

Мы провели несколько тестов и обнаружили, что c) определенно слишком медленный. Но у нас еще есть вариант а) и б). Сначала мы хотели перейти к пункту б), но после некоторых испытаний мы склонны больше к а).

Есть ли хорошая техническая причина, которая действительно сделала бы один вариант намного лучше, чем другой?

(Сейчас мы используем MySQL. Если это важно.)

Ответы [ 8 ]

10 голосов
/ 25 июня 2009

Я бы выбрал б), потому что он более точно отражает значение данных. Наличие структуры данных, в которой некоторые части должны игнорироваться, проблематично. Что если люди просто делают простое сравнение дат, предполагая, что год всегда один и тот же, но кто-то использовал другой год заполнителя, предполагая, что год все равно не имеет значения?

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

То, что в) плохо, я считаю, вне разумного обсуждения :-). И я не думаю о соображениях производительности ...

2 голосов
/ 25 июня 2009

Я бы использовал поле даты и, хотя он и не был нужен, все равно сохранял бы и год. Просто разденьте его, когда вам придется его распечатать / использовать. Есть несколько причин:

  1. Вы можете узнать, что позже указать клиент действительно хочет, чтобы вы сохранить дату. В этом случае вы не нужно вносить какие-либо изменения в ваш структура базы данных.
  2. Вы можете использовать функции даты SQL для сравнения дат, если это необходимо. Если у вас есть день и месяц в отдельных полях, вам нужно гораздо больше кода, например Рассчитайте разницу между двумя датами (високосные годы и т. д.).

Причины выбора б) также могут быть легко решены с помощью этих функций даты SQL. Вы можете легко выбрать события за определенный месяц, например, в одном запросе.

1 голос
/ 12 января 2016

Я также столкнулся с той же проблемой, в моем случае мне нужно получить данные на основе определенного дня в месяце, который повторяется ежегодно. Я использовал «ДАТА» и запрос, как этот

SELECT * FROM test_table WHERE MONTH(date) = 1 AND DAY(date) = 14

результат, подобный этому

enter image description here

Преимущество

  1. Я могу использовать возможности MySQL.
  2. Уменьшить вычисления на стороне клиента.
  3. Может использовать поле date_ для других вычислений

Я предлагаю использовать этот способ

это может быть полезно кому-то

1 голос
/ 25 июня 2009

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

 first_event | interval | interval_unit
-------------+--------------------------
  2009-01-01 |        6 | 'month'
  2009-02-01 |        1 | 'year'

К сожалению, MySQL не имеет типа данных INTERVAL, поэтому потребуется два столбца и небольшая часть последующей обработки, но я думаю, что это наиболее гибкий способ решения проблемы.

1 голос
/ 25 июня 2009

Я бы выбрал b), потому что это значительно упростит запросы: вы сможете очень просто восстановить все события в диапазоне (декабрь, определенный день, диапазон дней). Если вы выберете a) - не забудьте установить год на определенный для сравнения и извлечения.

0 голосов
/ 25 июня 2009

Я бы выбрал номер дня в году (например, одно число от 0 до 365, а затем добавил бы его к 1 января конкретного года, который вас интересует.

Если вы не хотите выполнять дополнительную математику из вышеприведенного решения, то используйте два поля: одно для месяца и одно для дня (но не забудьте обновить оба, когда это необходимо!).

Помните, что вам приходится иметь дело с високосными годами, поэтому использование поля даты - плохая идея, поскольку вам придется хранить даты с двумя годами - один високосный, а другой - не очень сложный!

0 голосов
/ 25 июня 2009

Выберите ONE int field, например, 1601 для 1 января.

0 голосов
/ 25 июня 2009

Я бы тоже принял сторону b), но для экономии места используйте TINYINT для месяца (от 0 до 255) и SMALLINT (от -32 768 до 32 767) для года.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...