Хранение данных в одном столбце является предпочтительным способом, поскольку они неразрывно связаны. Момент времени - это единая информация, а не две.
Распространенный способ хранения данных даты / времени, используемых многими «за сценой» многими продуктами, заключается в преобразовании их в десятичное значение, где «дата» - это целая часть десятичного значения, а «время» - дробная часть. значение. Итак, 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;
Постоянный столбец можно затем индексировать, что позволяет быстро сортировать и т. Д. По времени суток.
Если вы хотите разделить дату и время на два поля для отображения, вы должны понимать, что форматирование должно выполняться на клиенте, а не на сервере.