시간을 데이터베이스 테이블에 저장하고 싶지만 시간과 분만 저장하면됩니다. DATETIME을 사용하고 날짜의 다른 구성 요소를 무시할 수 있다는 것을 알고 있지만 실제로 필요한 것보다 더 많은 정보를 저장하지 않고이를 수행하는 가장 좋은 방법은 무엇입니까?
시간을 데이터베이스 테이블에 저장하고 싶지만 시간과 분만 저장하면됩니다. DATETIME을 사용하고 날짜의 다른 구성 요소를 무시할 수 있다는 것을 알고 있지만 실제로 필요한 것보다 더 많은 정보를 저장하지 않고이를 수행하는 가장 좋은 방법은 무엇입니까?
답변:
자정을 지난 분의 정수로 저장할 수 있습니다.
예.
0 = 00:00
60 = 01:00
252 = 04:12
그러나 시간을 재구성하려면 몇 가지 코드를 작성해야하지만 까다로워서는 안됩니다.
SQL Server 2008+를 사용하는 경우 TIME데이터 유형을 고려하십시오 . 더 많은 사용 예제가있는 SQLTeam 기사 .
DATETIME 시작 DATETIME 종료
대신 event_start 및 event_end 와 같은 레이블이 붙은 두 개의 DATETIME 값 을 사용 하시기 바랍니다 .
시간은 복잡한 사업
이제 세계 대부분이 대부분의 측정에 대해 옳든 그르 든 데 너리 기반 미터법을 채택했습니다. 이것은 전반적으로 좋습니다. 왜냐하면 적어도 우리 모두는 ag가 ml이고, 입방 cm라는 것에 동의 할 수 있기 때문입니다. 적어도 대략 그렇게. 미터법에는 많은 결함이 있지만 적어도 국제적으로는 지속적으로 결함이 있습니다.
그러나 시간이 지남에 따라 우리는 있습니다. 1 초에 1000 밀리 초, 60 초에서 1 분, 60 분에서 1 시간, 반나절마다 12 시간, 월별 약 30 일, 해당 월 및 연도에 따라 다르며, 각 국가는 다른 국가와 시간 오프셋이 있습니다. , 시간 형식은 국가마다 다릅니다.
소화해야 할 것은 많지만 길고 짧은 것은 그러한 복잡한 시나리오가 간단한 해결책을 갖는 것이 불가능합니다.
일부 모서리는 잘릴 수 있지만 더 현명한 부분이 있습니다.
여기에 대한 최고의 답변은 자정 이후에 몇 분의 정수를 저장하는 것이 완벽하게 합리적으로 보일 수 있음을 시사하지만 어려운 방법으로 그렇게하는 것을 피하는 법을 배웠습니다.
두 개의 DATETIME 값을 구현하는 이유는 정확도, 해상도 및 피드백의 증가 때문입니다.
이는 디자인이 원하지 않는 결과를 생성 할 때 매우 유용합니다.
필요한 것보다 더 많은 데이터를 저장하고 있습니까?
처음에는 내가 필요로하는 것보다 더 많은 정보가 저장되고있는 것처럼 보일 수 있지만이 히트를 가져야 할 좋은 이유가 있습니다.
이 추가 정보를 저장하면 거의 항상 장기적으로 시간과 노력을 절약 할 수 있습니다. 왜냐하면 누군가 무언가가 얼마나 오래 걸 렸는지 들었을 때 이벤트가 언제 어디서 일어 났는지 알고 싶어하기 때문입니다.
거대한 행성입니다
과거에 나는이 행성에 내 나라 외에 다른 나라가 있다는 것을 무시한 죄를지었습니다. 당시에는 좋은 생각처럼 보였지만 이로 인해 항상 문제, 두통 및 시간 낭비가 발생했습니다. 항상 모든 시간대를 고려하십시오.
씨#
DateTime은 C #의 문자열로 멋지게 렌더링됩니다. ToString (string Format) 메서드는 간결하고 읽기 쉽습니다.
예
new TimeSpan(EventStart.Ticks - EventEnd.Ticks).ToString("h'h 'm'm 's's'")
SQL 서버
또한 응용 프로그램 인터페이스와 별도로 데이터베이스를 읽는 경우 dateTimes는 한 눈에 읽을 수 있으며 계산을 수행하는 것은 간단합니다.
예
SELECT DATEDIFF(MINUTE, event_start, event_end)
ISO8601 날짜 표준
SQLite를 사용하는 경우이 기능이 없으므로 대신 텍스트 필드를 사용하고 ISO8601 형식으로 저장합니다.
'2013-01-27T12 : 30 : 00 + 0000'
노트:
24 시간제를 사용합니다 *
ISO8601의 시간 오프셋 (또는 +0000) 부분은 GPS 좌표의 경도 값에 직접 매핑됩니다 (일광 절약 또는 전국을 고려하지 않음).
예
TimeOffset=(±Longitude.24)/360
... 여기서 ±는 동쪽 또는 서쪽 방향을 나타냅니다.
따라서 데이터와 함께 경도, 위도 및 고도를 저장할 가치가 있는지 고려할 가치가 있습니다. 이것은 응용 프로그램에 따라 다릅니다.
ISO8601은 국제 형식입니다.
위키는 http://en.wikipedia.org/wiki/ISO_8601 에서 더 자세한 정보를 얻을 수 있습니다.
날짜와 시간은 국제 시간으로 저장되며 오프셋은 시간이 저장된 위치에 따라 기록됩니다.
내 경험상 프로젝트를 시작할 때가 있다고 생각하는지 여부에 관계없이 항상 전체 날짜와 시간을 저장할 필요가 있습니다. ISO8601은 매우 훌륭하고 미래를 보장하는 방법입니다.
무료 추가 조언
체인처럼 이벤트를 함께 그룹화하는 것도 가치가 있습니다. 예를 들어 레이스를 기록하는 경우 전체 이벤트를 racer, race_circuit, circuit_checkpoints 및 circuit_laps별로 그룹화 할 수 있습니다.
제 경험상 누가 기록을 저장했는지 확인하는 것도 현명합니다. 트리거를 통해 채워진 별도의 테이블 또는 원래 테이블 내의 추가 열로.
더 많이 넣을수록 더 많이 나옵니다.
나는 가능한 한 공간적으로 경제적이 되려는 욕구를 완전히 이해하지만 정보를 잃어 버리는 대가로 그렇게하는 경우는 거의 없습니다.
데이터베이스의 경험 법칙은 제목에서 알 수 있듯이 데이터베이스는 데이터가있는만큼만 알려줄 수 있으며, 공백을 메우고 과거 데이터를 살펴 보는 데에는 비용이 많이들 수 있습니다.
해결책은 처음에 올바르게하는 것입니다. 이것은 말처럼 쉬운 일이지만 이제는 효과적인 데이터베이스 디자인에 대한 더 깊은 통찰력을 가지고 있어야하며, 이후에 처음부터 올바르게 만들 가능성이 훨씬 더 높아야합니다.
초기 설계가 좋을수록 나중에 수리 비용이 적게 듭니다.
내가 시간을 거슬러 올라갈 수 있다면 내가 거기에 도착했을 때 나 자신에게 말할 것이기 때문입니다.
일반 날짜 시간을 저장하고 나머지는 모두 무시하십시오. 날짜 시간을로드 할 수있을 때 int를로드하고, 조작하고, 날짜 시간으로 변환하는 코드를 작성하는 데 추가 시간을 소비하는 이유는 무엇입니까?
DATETIME데이터 유형은 저장하는 데 4 바이트가 SMALLINT걸리지 만 예를 들어 데이터 유형은 1/4 만 차지합니다. 수천 개의 행만있는 경우 큰 차이는 없지만 많은 회사에서 행하는 수백만 개의 행이있는 경우 공간 절약은 상당 할 것입니다.
SQL Server는 실제로 시간을 하루의 일부로 저장합니다. 예를 들어, 하루 종일 1 = 값 1입니다. 12 시간은 값 0.5입니다.
DATETIME 유형을 사용하지 않고 시간 값을 저장하려는 경우 십진수 형식으로 시간을 저장하는 동시에 DATETIME으로 간단하게 변환 할 수 있습니다.
예를 들면 :
SELECT CAST(0.5 AS DATETIME)
--1900-01-01 12:00:00.000
값을 DECIMAL (9,9)로 저장하면 5 바이트가 사용됩니다. 그러나 정밀도가 가장 중요하지 않은 경우 REAL은 4 바이트 만 소비합니다. 두 경우 모두 집계 계산 (즉, 평균 시간)은 숫자 값에서 쉽게 계산할 수 있지만 데이터 / 시간 유형에서는 계산할 수 없습니다.
정수 (HH * 3600 + MM * 60)로 변환하여 저장합니다. 작은 저장소 크기로 작업하기에 충분히 쉽습니다.
자정을지나 몇 분이 아니라 24 시간 시계로 SMALLINT로 저장합니다.
09:12 = 912 14:15 = 1415
"사람이 읽을 수있는 형식"으로 다시 변환 할 때 오른쪽에서 두 문자 만 콜론 ":"을 삽입합니다. 필요한 경우 0이있는 왼쪽 패드. 각 방식으로 수학을 저장하고 몇 바이트 (varchar에 비해)를 사용하고 값을 영숫자가 아닌 숫자로 지정합니다.
그래도 꽤 구피 ... MS SQL에는 이미 IMHO에서 수년 동안 TIME 데이터 유형이 있어야했습니다 ...
당신이 요구하는 것은 분을 숫자로 저장할 변수입니다. 이는 다양한 유형의 정수 변수로 수행 할 수 있습니다.
SELECT 9823754987598 AS MinutesInput
그런 다음 프로그램에서 다음을 계산하여 원하는 형식으로 간단히 볼 수 있습니다.
long MinutesInAnHour = 60;
long MinutesInADay = MinutesInAnHour * 24;
long MinutesInAWeek = MinutesInADay * 7;
long MinutesCalc = long.Parse(rdr["MinutesInput"].toString()); //BigInt converts to long. rdr is an SqlDataReader.
long Weeks = MinutesCalc / MinutesInAWeek;
MinutesCalc -= Weeks * MinutesInAWeek;
long Days = MinutesCalc / MinutesInADay;
MinutesCalc -= Days * MinutesInADay;
long Hours = MinutesCalc / MinutesInAnHour;
MinutesCalc -= Hours * MinutesInAnHour;
long Minutes = MinutesCalc;
효율성 사용을 요청하는 문제가 발생합니다. 그러나 시간이 부족한 경우 nullable BigInt를 사용하여 분 값을 저장하십시오.
null 값은 시간이 아직 기록되지 않았 음을 의미합니다.
이제는 우주로의 왕복의 형태로 설명하겠습니다.
불행히도 테이블 열은 단일 유형 만 저장합니다. 따라서 필요에 따라 각 유형에 대해 새 테이블을 만들어야합니다.
예를 들면 :
MinutesInput = 0 .. 255 이면 TinyInt (위에서 설명한대로 변환)를 사용합니다.
MinutesInput = 256 .. 131071 이면 SmallInt 를 사용 합니다 (참고 : SmallInt의 최소값은 -32,768입니다. 따라서 위와 같이 변환하기 전에 전체 범위를 활용하기 위해 값을 저장 및 검색 할 때 32768을 부정하고 추가합니다).
MinutesInput = 131072 .. 8589934591 이면 Int 를 사용합니다 (참고 : 부정하고 필요에 따라 2147483648 추가).
MinutesInput = 8589934592 .. 36893488147419103231 이면 BigInt 를 사용합니다 (참고 : 필요에 따라 9223372036854775808 추가 및 부정).
MinutesInput> 36893488147419103231 이면 문자가 바이트이므로 필요에 따라 X를 증가시키는 VARCHAR (X)를 개인적으로 사용합니다. 나는 이것을 완전히 설명하기 위해 나중에이 대답을 다시 방문해야 할 것입니다 (또는 동료 스택 오버플로 이이 대답을 마칠 수 있습니다).
각 값에는 의심 할 여지없이 고유 한 키가 필요하므로 데이터베이스의 효율성은 저장된 값의 범위가 매우 작음 (0 분에 가깝게)과 매우 높음 (8589934591보다 큼) 사이의 적절한 혼합 인 경우에만 명백합니다.
저장되는 값이 실제로 36893488147419103231보다 큰 숫자에 도달 할 때까지 분 값을 저장하기 위해 고유 식별자 및 다른 int에 Int를 낭비 할 필요가 없기 때문에 분을 나타내는 단일 BigInt 열이있을 수 있습니다.
UTC 형식으로 시간을 절약하면 Kristen이 제안한 것처럼 더 나은 결과를 얻을 수 있습니다.
UTC에는 자오선 AM 또는 PM이 사용되지 않으므로 24 시간 시계를 사용하고 있는지 확인하십시오.
예:
표준 4 자리 형식을 사용하는 것이 여전히 선호됩니다.
현재 밀리 초 단위로 측정되는 / ticks로 저장합니다 . 업데이트 된 값은 값을보고 찾을 수 있습니다 .longbigintTimeSpan.TicksPerSecond
대부분의 데이터베이스에는 시간을 자동으로 틱으로 저장하는 DateTime 유형이 있지만 SqlLite와 같은 일부 데이터베이스의 경우 틱을 저장하는 것이 날짜를 저장하는 방법이 될 수 있습니다.
대부분의 언어는 Ticks→ TimeSpan→ 에서 쉽게 변환 할 수 Ticks있습니다.
예
C #에서 코드는 다음과 같습니다.
long TimeAsTicks = TimeAsTimeSpan.Ticks;
TimeAsTimeSpan = TimeSpan.FromTicks(TimeAsTicks);
그러나 SqlLite의 경우에는 소수의 다른 유형 만 제공하기 때문에주의하십시오. INT, REAL그리고 VARCHAR틱 수를 문자열 또는 INT결합 된 두 개의 셀로 저장해야합니다 . INT이는는 32 비트 부호있는 숫자 BIGINT이고은 64 비트 부호있는 숫자 이기 때문 입니다.
노트
그러나 개인적으로 선호하는 것은 날짜와 시간을 ISO8601문자열 로 저장하는 것 입니다.
IMHO 최고의 솔루션은 나머지 데이터베이스 (및 나머지 애플리케이션)에 시간을 저장하는 방법에 따라 어느 정도 다릅니다.
개인적으로 저는 SQLite와 함께 일했고 항상 절대 시간을 저장하기 유닉스 타임 스탬프 를 . 그래서 하루 중 시간을 다룰 때 (당신이 요청한 것처럼) 글렌 솔스 베리가 그의 대답에 쓴대로하고 자정 이후의 초 수를 저장합니다.
이 일반적인 접근 방식을 취할 때 사람들이 (나를 포함하여!) 어디서나 동일한 표준을 사용하면 코드를 읽는 것이 덜 혼란 스럽습니다.