#sql #sql-server
#sql #sql-сервер
Вопрос:
Я использую SQL Server 2008.
В моей базе данных есть несколько дат, которые, как я «думаю», я хочу разбить на более мелкие части. Даты — это дни рождения и смерти. Я хочу иметь возможность выводить их, например, запрашивая людей, которые родились в октябре или 12 мая или в 1945 году.
Мне сказали, что типичный способ сделать это — взять дату, разбить ее на более мелкие части и поместить каждую часть даты в отдельный столбец, вот так:
2001-03-12 00:00:00 // EventDate column
Добавьте эти столбцы:
2001 // EventYear column
03 // EventMonth column
12 // EventDay column
Во-первых, это хороший способ сделать это? Если да, то, во-вторых, могу ли я каким-то образом заставить SQL Server автоматически разбивать часть даты и помещать ее в свои собственные столбцы?
Я был бы признателен за идеи и решения.
Комментарии:
1. Сколько строк данных у вас в этой таблице?
2. В четырех-шести таблицах будет не более 10 000 строк. Я действительно хочу узнать «правильный» способ сделать это. Я не собираюсь просто делать это каким-то старым способом. Я уже могу сделать это четырьмя или пятью «неправильными» способами. Я хочу знать, как это сделает эксперт.
3. Что значит распределить по 4-6 таблицам?
4. У меня будет четыре или пять таблиц с датами. В каждой таблице может быть 2000 строк.
5. Я не вижу причин указывать Erik разделять каждый столбец datetime с целью запроса 2000 записей.
Ответ №1:
Я бы рекомендовал оставить его в качестве столбца даты, а затем использовать DatePart в запросах для фильтрации результатов.
Select * from TABLEX
where DatePart(YEAR,EventDate) = 1945
Комментарии:
1. Как это будет выполняться, когда запрос будет на 12 мая?
2. Это правильный способ справиться с манипулированием столбцами даты и времени. Нет смысла дублировать дату в несколько столбцов, если вы не говорите о базе данных, которая содержит миллионы записей, а производительность чрезвычайно важна. Эта функциональность имеет низкую стоимость и должна работать нормально.
3. У меня, конечно, не будет миллионов дат, возможно, всего несколько тысяч. Я хочу сделать это так, как если бы было миллион дат. Я бы предпочел написать запрос типа select * from DateTable где Year = 1945, чем указывать часть даты в каждом запросе.
4. Основное преимущество использования datepart заключается в том, что вам не нужно думать о создании нового столбца каждый раз, когда вы хотите разделить данные по-разному. Например … если вы решили, что хотите знать все события, произошедшие в субботу, вам не нужно создавать еще один столбец для day of the week, вы бы просто использовали datepart weekday .
5. Основным недостатком является то, что каждый запрос будет представлять собой tablescan, возможно , за исключением того, который включает год, месяц, день и т.д. в таком порядке (я не знаю, является ли DatePart переносимым, но частичные запросы определенно нет.)
Ответ №2:
Не похоже, что бизнес-требования сильно укреплены. По какой причине вам нужно было бы разделить разные части даты? Если вам это не нужно, я бы не стал.
Но, если вы обнаружите необходимость в этом, я бы использовал вычисляемые столбцы, которые сохраняются. При вставке будут некоторые накладные расходы, но поскольку не будет никаких обновлений существующих данных (дата вашего рождения и дата смерти не изменятся), вы не увидите никаких накладных расходов на производительность при выборе.
Что-то вроде этого:
create table DateTest
(
SomeDate datetime not null,
SomeYear as datepart(yy, somedate) persisted,
SomeMonth as datepart(mm, somedate) persisted,
SomeDay as datepart(dd, somedate) persisted
)
Комментарии:
1. 1 для вычисляемых столбцов, но не забудьте также добавить индекс, иначе у вас все равно будет сканирование таблицы с использованием столбцов. И вычисляемый столбец по году на самом деле не нужен. Вы можете использовать столбец даты непосредственно для этого.
2. Интересное решение. Это выше моего уровня опыта, но я собираюсь исследовать это и помнить об этом. Спасибо!
Ответ №3:
Вот что я делаю.
У меня есть таблица «lib.Dates». В качестве первичного ключа используется ДАТА.
В нем есть дополнительные столбцы с дополнительной информацией на эту дату. Это, например, день месяца, день до конца месяца, неделя года и т.д.
Объединение этой таблицы дат с датами позволяет мне: * Получить список всех дат (например, группировка продаж на человека по дате не будет иметь записи для нулевых продаж, таким образом, это может быть) * Делать забавные вещи, такие как все даты на 23-й неделе года, что обычно сложнее получить.
Это часть ряда таких таблиц, которые мои хранимые процедуры поддерживают ежедневно (-3 года, 5 лет).
Комментарии:
1. Вы имеете в виду
Calendar
таблицу, на которую может ссылаться любая другая таблица сdate
полемFOREIGN KEY
? Значит, никакой другой таблице не понадобятся сохраненные индексированные представления? Если да, 1 от меня.2. Да, точно. Он также принадлежит библиотечному проекту, который я поддерживаю — я иногда добавляю сюда новые таблицы. Особенно иногда очень приятна функция объединения (поскольку она позволяет мне получать список ВСЕХ дат, а не только дат, содержащих данные).
3. Да, похожие вопросы время от времени появляются в SO: «найти все даты, по которым заказы не принимались».
4. TomTom, это интересное решение, но для меня это слишком много. Я ценю, что вы познакомили меня с этой идеей.