Лучший способ хранить квартал и год в SQL Server? - PullRequest
4 голосов
/ 19 апреля 2011

Как лучше всего хранить квартал и год в базе данных? У меня есть таблица платежей, и мне нужно назначить квартал / год, чтобы было легко определить, за какой квартал был произведен платеж.

Я думал о:

a) добавление двух столбцов int к каждому платежу
б) добавление еще одной таблицы и добавление возможных значений на срок до 5 лет и использование идентификатора для объединения этой таблицы с платежами один.

Какие есть другие варианты? Может быть, некоторые из них лучше или / и легче поддерживать. Эта база данных будет использоваться с программой C #.

Ответы [ 8 ]

4 голосов
/ 19 апреля 2011

Если вам нужно использовать отдельный год и квартал вместо даты (поскольку у вас, похоже, есть особые требования к отчетности), я бы взял tinyint за квартал и smallint за год и сохранил их в PAYMENT Сам стол.

Я бы не стал хранить его в другой таблице. Это плохо, так как:

  • Вы должны убедиться, что вы произвели достаточно лет / кварталов
  • Вы должны присоединиться и использовать внешний ключ

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

ПОЧЕМУ

Давайте представим, что вам нужно получить

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

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

3 голосов
/ 19 апреля 2011

Я всегда использовал значение даты и времени с 1 января / апреля / июля / октября, представляющего каждый квартал.Упрощает вычисление дат начала / окончания квартала:

  • Дата начала: сам столбец datetime.
  • Конечные данные: dateadd(month,3,quarterColumn)

Другой альтернативой будет ISO 8601 .Вот профиль ISO 8601 для использования в интернет-протоколах: RFC 3339 (предлагаемый стандарт).

Представление ISO 8601 каждого квартала 2011 года выглядит следующим образом:

  • 2011-01-01 / P3M
  • 2011-04-01 / P3M
  • 2011-07-01 / P3M
  • 2011-10-01 / P3M

Выше указывается длительность по дате начала и продолжительности (в данном случае 3 месяца).

Преимущество форматов даты / времени ISO 8601 состоит в том, что строки имеют вид (A) удобочитаемые, (B) они сопоставляют должным образом, (C) их легко анализировать и (D) это международный стандарт.

Некоторые люди «расширяют» обозначение недели ISO 8601, где неделягод выглядит как 2011W32 (32-я неделя 2011 года), с точностью до четверти.Используя это неофициальное расширение, кварталы 2011 года выглядят следующим образом:

  • 2011Q1
  • 2011Q2
  • 2011Q3
  • 2011Q4
2 голосов
/ 19 апреля 2011

Как насчет использования вычисляемых столбцов на основе даты платежа? Я бы предпочел сделать это, чем иметь дату и квартал / год, которые могут быть не синхронизированы. С другой стороны, я полагаю, что вам может потребоваться возможность иметь другой год / квартал, отличный от даты, которая указывает, в каком случае вам нужно хранить их отдельно. По крайней мере, я бы подумал об использовании вычисляемых столбцов, так как это кажется лучшим способом обеспечения целостности.

1 голос
/ 19 апреля 2011

Хранение квартала и года в базе данных зависит от того, как организованы ваши платежные данные.Примеры будут;сколько различных значений платежа вставляются.Будут ли меняться диапазоны квартала / года?и т. д.

Один из хороших методов «определения» диапазона квартал / год - создание отдельной таблицы с полем «DateTime», которое идентифицирует квартал.Вам не нужно присоединяться к таблице, вам просто нужно заняться программированием на C #, чтобы выяснить, попадает ли диапазон в определенный квартал выплаты.

Например:

Table 1: Payments
-----------------
paymentID (int)
paymentAmount (double(7,2))
paymentDateTime (DateTime)

Table 2: QuarterYear
--------------------
quarterYearID (int)
dateFrom (date)
dateTo (date)
quarter (tinyint)
description (varchar)

Пример данных

paymentID | paymentAmount |   paymentDateTime
------------------------------------------------
    1     |    20.24      |  2011-04-18 08:14:20
    2     |    34.15      |  2011-04-19 07:42:15
    3     |    51.87      |  2011-04-20 13:04:22

quarterYearID |  dateFrom  |   dateTo   | quarter |  description
-----------------------------------------------------------------
      1       | 2011-01-01 | 2011-03-31 |    1    | first quarter
      2       | 2011-04-01 | 2011-06-30 |    2    | second quarter 
      3       | 2011-07-01 | 2011-09-31 |    3    | third quarter
      4       | 2011-10-01 | 2011-12-31 |    4    | forth quarter   

Пример Запрос на получение всех платежей для «квартала 2» dateValue - это динамически извлекаемая переменная из таблицы платежей,C # будет обрабатывать значение dateValue.

SELECT quarter FROM QuarterYear WHERE cast('dateValue' AS date) BETWEEN dateFrom AND dateTo;
1 голос
/ 19 апреля 2011

Вы можете даже использовать один tinyint. Этого достаточно для хранения в форме YYQ, например, 111, 112,113,114, 121 ... в течение нескольких лет.

1 голос
/ 19 апреля 2011

Я согласен, что два целых в порядке.

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

1 голос
/ 19 апреля 2011

Как насчет двух целых, одного на год и одного на квартал (1-4). Это то, что вы подразумевали под опцией «а»?

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

1 голос
/ 19 апреля 2011

Для чего-то такого простого, я бы просто сохранил 2 столбца типа int и построил (ключевые) даты, используя dateadd, когда требуется использовать диапазоны дат.

Другим вариантом является столбец с одной датой, для которого можно сохранить первый день квартала, поэтому 4 даты в году будут: 1 января, 1 апреля, 1 июля, 1 октября. Вы можете легко извлечь квартал, год, используя datepart Q и Y.

...