데이터를 단일 열에 저장하는 것이 바람직한 방법입니다. 데이터는 불가분의 관계로 연결되어 있기 때문입니다. 특정 시점은 두 가지가 아닌 단일 정보입니다.
많은 제품에서 "장면 뒤에"사용 된 날짜 / 시간 데이터를 저장하는 일반적인 방법은 "날짜"가 10 진수 값의 정수 부분이고 "시간"이 소수 인 10 진수 값으로 변환하는 것입니다. 값. 따라서 1900-01-01 00:00:00은 0.0으로 저장되고 2016 년 9 월 20 일 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;
그런 다음 지속 된 열을 인덱싱하여 시간별로 빠른 정렬 등을 수행 할 수 있습니다.
표시 목적으로 날짜와 시간을 두 필드로 나누는 것을 고려중인 경우 서버가 아닌 클라이언트에서 형식을 지정해야합니다.