Збереження даних в одному стовпчику є кращим способом, оскільки вони нерозривно пов'язані. Момент часу - це цілий інформаційний матеріал, а не два.
Поширений спосіб зберігання даних про дату / час, використовуваний "поза кадром" багатьма продуктами, - це перетворення їх у десяткове значення, де "дата" є цілою частиною десяткового значення, а "час" - дробовою. значення. Так, 1900-01-01 00:00:00 зберігається як 0,0, а 20 вересня 2016 9:34:00 зберігається як 42631,39861. 42631 - кількість днів з 1900-01-01. .39861 - це час, що минув з півночі. Не використовуйте для цього безпосередньо десятковий тип, використовуйте явний тип дати / часу; моя думка тут - лише ілюстрація.
Зберігання даних у двох окремих стовпцях означає, що вам потрібно буде об’єднати обидва значення стовпців будь-коли, коли ви хочете побачити, чи даний момент часу є раніше чи пізніше, ніж збережене значення.
Якщо ви зберігаєте значення окремо, ви незмінно наштовхуєтесь на "помилки", які важко виявити. Візьмемо для прикладу наступне:
IF OBJECT_ID('tempdb..#DT') IS NOT NULL
DROP TABLE #DT;
CREATE TABLE #DT
(
dt_value DATETIME NOT NULL
, d_value DATE NOT NULL
, t_value TIME(0) NOT NULL
);
DECLARE @d DATETIME = '2016-09-20 09:34:00';
INSERT INTO #DT (dt_value, d_value, t_value)
SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
SET @d = '2016-09-20 11:34:00';
INSERT INTO #DT (dt_value, d_value, t_value)
SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
/* show all rows with a date after 2016-07-01 11:00 am */
SELECT *
FROM #DT dt
WHERE dt.dt_value >= '2016-07-01 11:00:00';
/* show all rows with a date after 2016-07-01 11:00 am */
SELECT *
FROM #DT dt
WHERE dt.d_value >= CONVERT(DATE, '2016-07-01')
AND dt.t_value >= CONVERT(TIME(0), '11:00:00');
У наведеному вище коді ми створюємо тестову таблицю, заповнюючи її двома значеннями, а потім виконуємо простий запит проти цих даних. Перший SELECT
повертає обидва рядки, однак другий SELECT
повертає лише один рядок, що може бути не бажаним результатом:
Правильний спосіб фільтрації діапазону дати / часу, коли значення знаходяться в дискретних стовпцях, на що в коментарях вказував @ypercube:
WHERE dt.d_value > CONVERT(DATE, '2016-07-01') /* note there is no time component here */
OR (
dt.d_value = CONVERT(DATE, '2016-07-01')
AND dt.t_value >= CONVERT(TIME(0), '11:00:00')
)
Якщо вам потрібен розділений часовий компонент для цілей аналізу , ви можете розглянути можливість додавання обчисленої, збереженої стовпця для часової частини значення:
ALTER TABLE #DT
ADD dt_value_time AS CONVERT(TIME(0), dt_value) PERSISTED;
SELECT *
FROM #dt;
Стійкий стовпчик може бути індексований, що дозволяє робити швидкі сортування тощо за часом дня.
Якщо ви плануєте розділити дату і час на два поля для цілей відображення, ви повинні усвідомити, що форматування повинно здійснюватися у клієнта, а не на сервері.