Chcę przechowywać czasy w tabeli bazy danych, ale muszę przechowywać tylko godziny i minuty. Wiem, że mogę po prostu użyć DATETIME i zignorować inne składniki daty, ale jaki jest najlepszy sposób, aby to zrobić bez przechowywania większej ilości informacji, niż faktycznie potrzebuję?
sql-server
database
database-design
datetime
Matthew Dresser
źródło
źródło
Odpowiedzi:
Możesz zapisać to jako liczbę całkowitą określającą liczbę minut po północy:
na przykład.
Musiałbyś jednak napisać jakiś kod, aby odtworzyć czas, ale to nie powinno być trudne.
źródło
Jeśli używasz SQL Server 2008+, rozważ
TIME
typ danych. Artykuł SQLTeam zawierający więcej przykładów użycia.źródło
Błagam, aby zamiast tego użyć dwóch wartości DATETIME , oznaczonych czymś w rodzaju event_start i event_end .
Czas to skomplikowana sprawa
Większość świata przyjęła obecnie system metryczny oparty na denery dla większości pomiarów, słusznie lub nie. Ogólnie jest to dobre, bo przynajmniej wszyscy możemy się zgodzić, że ag, to ml, to cm sześcienny. Przynajmniej mniej więcej tak. System metryczny ma wiele wad, ale przynajmniej jest konsekwentnie błędny na całym świecie.
Z czasem jednak mamy; 1000 milisekund na sekundę, 60 sekund do minuty, 60 minut do godziny, 12 godzin na każde pół dnia, około 30 dni w miesiącu, które różnią się w zależności od miesiąca, a nawet roku, każdy kraj ma swój czas od innych , sposób formatowania czasu w każdym kraju jest różny.
To dużo do przetrawienia, ale długa i krótka to niemożliwe, aby tak złożony scenariusz miał proste rozwiązanie.
Niektóre rogi można wyciąć, ale są takie, w których rozsądniej jest tego nie robić
Chociaż górna odpowiedź sugeruje, że zapisywanie liczby całkowitej minut po północy może wydawać się całkiem rozsądne, nauczyłem się tego unikać na własnej skórze.
Powody wprowadzenia dwóch wartości DATETIME to zwiększenie dokładności, rozdzielczości i sprzężenia zwrotnego.
Są one bardzo przydatne, gdy projekt daje niepożądane rezultaty.
Czy przechowuję więcej danych niż jest to wymagane?
Początkowo może się wydawać, że przechowywanych jest więcej informacji niż potrzebuję, ale jest dobry powód, aby przyjąć to trafienie.
Przechowywanie tych dodatkowych informacji prawie zawsze oszczędza mi czas i wysiłek na dłuższą metę, ponieważ nieuchronnie stwierdzam, że gdy ktoś mówi, ile czasu zajęło, będzie chciał wiedzieć, kiedy i gdzie miało miejsce wydarzenie.
To ogromna planeta
W przeszłości byłem winny ignorowania faktu, że oprócz mojego własnego są inne kraje na tej planecie. Wtedy wydawało się to dobrym pomysłem, ale to ZAWSZE powodowało problemy, bóle głowy i późniejszą stratę czasu. ZAWSZE bierz pod uwagę wszystkie strefy czasowe.
DO#
DateTime ładnie renderuje się do ciągu w C #. Metoda ToString (format ciągu znaków) jest kompaktowa i łatwa do odczytania.
Na przykład
Serwer SQL
Ponadto, jeśli czytasz bazę danych oddzielnie dla interfejsu aplikacji, dateTimes jest przyjemny do odczytania na pierwszy rzut oka, a wykonywanie na nich obliczeń jest proste.
Na przykład
Standard daty ISO8601
Jeśli używasz SQLite, nie masz tego, więc zamiast tego użyj pola tekstowego i zapisz je w formacie ISO8601, np.
„2013-01-27T12: 30: 00 + 0000”
Uwagi:
Używa 24-godzinnego zegara *
Przesunięcie czasu (lub +0000) części ISO8601 jest odwzorowywane bezpośrednio na wartość długości geograficznej współrzędnej GPS (nie biorąc pod uwagę czasu letniego lub całego kraju).
Na przykład
... gdzie ± odnosi się do kierunku wschodniego lub zachodniego.
Dlatego warto zastanowić się, czy warto przechowywać razem z danymi długość i szerokość geograficzną oraz wysokość. Zależy to od zastosowania.
ISO8601 to format międzynarodowy.
Więcej szczegółów można znaleźć na wiki, pod adresem http://en.wikipedia.org/wiki/ISO_8601 .
Data i czas są przechowywane w czasie międzynarodowym, a przesunięcie jest rejestrowane w zależności od tego, gdzie na świecie czas został zapisany.
Z mojego doświadczenia wynika, że zawsze istnieje potrzeba przechowywania pełnej daty i godziny, niezależnie od tego, czy myślę, że jest to moment rozpoczęcia projektu. ISO8601 to bardzo dobry, przyszłościowy sposób na zrobienie tego.
Dodatkowe porady gratis
Warto też pogrupować wydarzenia jak łańcuch. Np. Jeśli nagrywasz wyścig, całe zdarzenie może być pogrupowane według wyścigów, wyścigów, punktów kontrolnych obwodu i okrążeń.
Z mojego doświadczenia wynika również, że mądrze jest określić, kto przechował zapis. Albo jako oddzielna tabela wypełniana przez wyzwalacz lub jako dodatkowa kolumna w oryginalnej tabeli.
Im więcej w to wkładasz, tym więcej wychodzisz
W pełni rozumiem pragnienie oszczędzania przestrzeni, jak to tylko możliwe, ale rzadko robiłbym to kosztem utraty informacji.
Praktyczna zasada dotycząca baz danych jest taka, jak mówi tytuł, baza danych może powiedzieć tylko tyle, ile zawiera dane, a cofanie się do danych historycznych i wypełnianie luk może być bardzo kosztowne.
Rozwiązaniem jest poprawienie tego za pierwszym razem. Z pewnością łatwiej to powiedzieć niż zrobić, ale teraz powinieneś mieć głębszy wgląd w efektywny projekt bazy danych, a następnie mieć znacznie większą szansę na poprawienie go za pierwszym razem.
Im lepszy projekt początkowy, tym mniej kosztowne będą późniejsze naprawy.
Mówię to wszystko tylko dlatego, że gdybym mógł cofnąć się w czasie, to właśnie to powiedziałbym sobie, kiedy tam dotarłem.
źródło
Po prostu przechowuj zwykłą datę i godzinę i ignoruj wszystko inne. Po co poświęcać więcej czasu na pisanie kodu, który ładuje int, manipuluje nim i konwertuje go na datę i godzinę, skoro można po prostu załadować datę i godzinę?
źródło
DATETIME
przechowywanie typu danych zajmuje 4 bajty, podczas gdySMALLINT
na przykład zajmuje tylko jedną czwartą tego. Nie ma dużej różnicy, jeśli masz tylko kilka tysięcy wierszy, ale jeśli masz wiele milionów wierszy, jak wiele firm, oszczędność miejsca będzie znaczna.ponieważ nie wspomniałeś o tym trochę, jeśli korzystasz z SQL Server 2008, możesz użyć typu danych czas, w przeciwnym razie użyj minut od północy
źródło
SQL Server faktycznie przechowuje czas jako ułamki dnia. Na przykład 1 cały dzień = wartość 1. 12 godzin to wartość 0,5.
Jeśli chcesz przechowywać wartość czasu bez użycia typu DATETIME, przechowywanie czasu w postaci dziesiętnej będzie odpowiadało tej potrzebie, jednocześnie ułatwiając konwersję na DATETIME.
Na przykład:
Zapisanie wartości jako DECIMAL (9,9) zajęłoby 5 bajtów. Jednak jeśli precyzja nie ma największego znaczenia, RZECZYWISTA zajęłaby tylko 4 bajty. W obu przypadkach łączne obliczenia (tj. Średni czas) można łatwo obliczyć na podstawie wartości liczbowych, ale nie na typach danych / czasu.
źródło
Zamieniłbym je na liczbę całkowitą (HH * 3600 + MM * 60) i zapisałbym w ten sposób. Mały rozmiar pamięci masowej i nadal wystarczająco łatwy w obsłudze.
źródło
Jeśli używasz MySQL, użyj typu pola TIME i powiązanej funkcjonalności, która jest dostarczana z TIME.
00:00:00 to standardowy format czasu w systemie Unix.
Jeśli kiedykolwiek będziesz musiał spojrzeć wstecz i przejrzeć tabele ręcznie, liczby całkowite mogą być bardziej zagmatwane niż rzeczywisty znacznik czasu.
źródło
Wypróbuj smalldatetime. Może nie dać ci tego, czego chcesz, ale pomoże ci w twoich przyszłych potrzebach w zakresie manipulacji datą / godziną.
źródło
Czy na pewno będziesz potrzebować tylko godzin i minut? Jeśli chcesz zrobić z nim coś sensownego (na przykład obliczyć okresy między dwoma takimi punktami danych), brak informacji o strefach czasowych i czasie letnim może dać nieprawidłowe wyniki. Strefy czasowe może nie mają zastosowania w twoim przypadku, ale czas letni z pewnością tak.
źródło
Zamiast minut po północy przechowujemy go jako zegar 24-godzinny, jako SMALLINT.
09:12 = 912 14:15 = 1415
podczas konwersji z powrotem do „postaci czytelnej dla człowieka” po prostu wstawiamy dwukropek „:” dwa znaki z prawej strony. W razie potrzeby dopełnij lewymi zerami. Zapisuje matematykę w obie strony i wykorzystuje kilka mniej bajtów (w porównaniu z varchar), a także wymusza, aby wartość była numeryczna (a nie alfanumeryczna)
Dość głupio ... w MS SQL powinien istnieć typ danych TIME już od wielu lat IMHO ...
źródło
Myślę, że pytasz o zmienną, która będzie przechowywać minuty jako liczbę. Można to zrobić za pomocą różnych typów zmiennych całkowitych:
Następnie w swoim programie możesz po prostu wyświetlić to w żądanej formie, obliczając:
Problem pojawia się, gdy prosisz o wykorzystanie wydajności. Ale jeśli masz mało czasu, to prostu użyj wartości zerowej BigInt do przechowywania wartości minut.
Wartość null oznacza, że czas nie został jeszcze zarejestrowany.
Teraz wyjaśnię w formie podróży w obie strony do kosmosu.
Niestety kolumna tabeli będzie przechowywać tylko jeden typ. W związku z tym konieczne będzie utworzenie nowej tabeli dla każdego typu, zgodnie z wymaganiami.
Na przykład:
Jeśli MinutesInput = 0 ... 255, użyj TinyInt (Konwertuj zgodnie z opisem powyżej).
Jeśli MinutesInput = 256 .. 131071, użyj SmallInt (Uwaga: minimalna wartość SmallInt to -32 768. Dlatego zaneguj i dodaj 32768 podczas przechowywania i pobierania wartości, aby wykorzystać pełny zakres przed konwersją jak powyżej).
Jeśli MinutesInput = 131072 .. 8589934591, użyj wartości Int (Uwaga: w razie potrzeby dodaj wartość ujemną i 2147483648).
Jeśli MinutesInput = 8589934592 .. 36893488147419103231, użyj BigInt (Uwaga: w razie potrzeby dodaj i zaneguj 9223372036854775808 ).
Jeśli MinutesInput> 36893488147419103231, wtedy osobiście użyłbym VARCHAR (X) zwiększając X w razie potrzeby, ponieważ znak jest bajtem. Będę musiał ponownie przejrzeć tę odpowiedź w późniejszym terminie, aby opisać to w całości (lub może inny znajomy stackoverflowee może dokończyć tę odpowiedź).
Ponieważ każda wartość będzie niewątpliwie wymagać unikalnego klucza, wydajność bazy danych będzie widoczna tylko wtedy, gdy zakres przechowywanych wartości będzie dobrym połączeniem między bardzo małym (blisko 0 minut) i bardzo wysokim (większym niż 8589934591).
Dopóki przechowywane wartości nie osiągną liczby większej niż 36893488147419103231, równie dobrze możesz mieć pojedynczą kolumnę BigInt do reprezentowania minut, ponieważ nie będziesz musiał marnować wartości Int na unikalny identyfikator i inną liczbę int do przechowywania wartości minut.
źródło
Oszczędność czasu w formacie UTC może pomóc lepiej, jak zasugerowała Kristen.
Upewnij się, że korzystasz z zegara 24-godzinnego, ponieważ w UTC nie ma południka AM ani PM.
Przykład:
Nadal preferowane jest użycie standardowego czterocyfrowego formatu.
źródło
Zapisz
ticks
jakolong
/bigint
, które są obecnie mierzone w milisekundach. Zaktualizowaną wartość można znaleźć, patrząc naTimeSpan.TicksPerSecond
wartość.Większość baz danych ma typ DateTime, który automatycznie przechowuje czas jako ticky za kulisami, ale w przypadku niektórych baz danych, np. SqlLite, przechowywanie ticków może być sposobem na przechowywanie daty.
Większość języków umożliwia łatwą konwersję z
Ticks
→TimeSpan
→Ticks
.Przykład
W C # kod wyglądałby tak:
Należy jednak pamiętać, ponieważ w przypadku SqlLite, który oferuje tylko niewielką liczbę różnych typów, którymi są;
INT
,REAL
IVARCHAR
będzie konieczne zachowanie numeru kleszczy jako ciąg dwóch lubINT
komórek łącznie. Dzieje się tak, ponieważINT
jest to 32-bitowy numer zeBIGINT
znakiem, podczas gdy jest to 64 -bitowy numer ze znakiem.Uwaga
Jednak moim osobistym preferencją byłoby przechowywanie daty i godziny jako
ISO8601
ciągu.źródło
IMHO to, które rozwiązanie jest najlepsze, zależy w pewnym stopniu od tego, jak przechowujesz czas w pozostałej części bazy danych (i reszcie aplikacji)
Osobiście pracowałem z SQLite i staram się zawsze używać uniksowych znaczników czasu do przechowywania czasu absolutnego, więc gdy mam do czynienia z porą dnia (tak jak prosisz) robię to, co Glen Solsberry pisze w swojej odpowiedzi i przechowuję liczbę sekund od północy
Przyjmując to ogólne podejście, ludzie (w tym ja!) Czytający kod są mniej zdezorientowani, jeśli wszędzie używam tego samego standardu
źródło