2013-08-29 13 views
7

Chcę przechowywać częściowe daty w relacyjnej bazie danych (MySQL, PostgreSQL itp.). Na przykład wkładem może być właśnie rok (2013); rok i miesiąc (2013-08); lub rok, miesiąc i dzień (2013-08-29). Nie mogę po prostu użyć zwykłego typu DATY, ponieważ rok zostanie rozszerzony do 2013-01-01, a to nieodróżnialne od roku, miesiąca i dnia.Przechowywanie częściowych dat w bazie danych

Myślałem o oddzieleniu daty na trzy oddzielne pola (rok, miesiąc i dzień jako liczby całkowite), ale tracę wszystkie szczegóły dat w DBS i muszę zarządzać większymi wskaźnikami.

Moja druga myśl polega na zapisaniu go jako DATĘ i dodaniu innej kolumny z informacją, jak dokładna jest data. Na przykład "2013-08-01" i "miesiąc" oznaczałyby, że data jest dokładna tylko do miesiąca (2013-08). "2013-08-01" i "dzień" oznaczałyby pełną datę 2013-08-01.

Jaki jest najlepszy sposób na zrobienie tego?

+0

Proszę podać kilka kodów. –

+0

To wydaje się icky. Nie mogę wymyślić czystego/prostego sposobu na przedstawienie tych danych. – user2246674

+0

Jakiego rodzaju zapytania chcesz uruchomić? –

Odpowiedz

2

myślę, że jesteśmy dwie możliwe drogi:

(1) Store podciągi nieaktualne, jak:

'2013'    -- year 2013 
'2013-01'   -- year 2013, January 
'2013-01-01'   -- year 2013, January 1 

(2) Magazynowe 3 różnych kolumn, rok, miesiąc, dzień (można zbudować indeks Rok + Miesiąc + Data bez proble)

2013 null null  -- year 2013 
2013  1 null  -- year 2013, January 
2013  1  1  -- year 2013, January 1st 

Który z nich jest najlepszy, zależy od tego, w jaki sposób chcesz wysłać zapytanie do danych. Załóżmy, że masz procedurę przechowywaną i chcesz przekazać parametr, aby wszystkie wiersze stanęły.

W przypadku (1), przekazać ciąg @Date = '2013-01' jako parametr i chcesz uzyskać wszystkie wiersze, gdzie rok = 2013 i miesiąc = 01. Zatem klauzula where byłoby jak:

where left(Date, len(@Date)) = @Date 

w przypadku (2), mijamy trzy parametry - @Year = 2013, @Month = 1, @Day = null i klauzula where byłoby coś jak:

where 
    Year = @Year and -- Supposing @Year is always not null 
    (@Month is null or @Month is not null and Month = @Month) and 
    (@Day is null or @Day is not null and Day = @Day) 

Może być bardziej złożony w zależności od tego, jak chcesz przetwarzać wiersze. Na przykład, jeśli podasz parametr taki jak 2013-01, czy chcesz uzyskać wiersze, w których month = null czy nie?

Z drugiej strony, jeśli chcesz przekazać datę i sprawdzić, czy mieści się w zakresie dat, to propozycja Gordona Linoffa jest dobra.

+0

+1 za wzięcie pod uwagę sposobu, w jaki dane te mają być sprawdzane. –

2

Być może najlepszym sposobem jest potraktować je jako rozpiętość czasu i mieć effdate i enddate. Możesz reprezentować dowolny czas, jaki chcesz. Rok byłby taki jak "2012-01-01" i "2012-12-31". Pojedyncza data to "2013-08-28" i "2013-08-28".

Dałoby to również elastyczność w rozszerzeniu reprezentacji w celu obsługi kwartałów lub innych grup czasu.

+0

+1 dobry, jeśli OP chce sprawdzić datę w zakresie –

+0

Mogę przechowywać rok jako "2012-01-01" (włącznie) do "2013-01-01" wyłącznie. Dzień będzie "2013-08-28" (włącznie) do "2013-08-29" (wyłączne). Ułatwia ustalenie, czy data/czas znajdują się w zakresie, jeśli wybrano opcję "EndDate" i "StartDate" włącznie. –

+0

@WW. dobry punkt –

1

Z tego, co określiłeś, nie chcesz używać date_trunc, ponieważ chcesz 2013-08 oznaczać "miesiąc sierpnia 2013", a nie rzeczywistą datę! Więc wydajesz się mniej przejmować chwilami, a więcej o okresach.

Myślę, że należy po prostu przechowywać ciągi. Jeśli przechowujesz:

2013 
2013-08 
2013-09-25 

jako struny powinieneś mieć się dobrze. Są w porządku. Dodatkowo potrzebujesz tylko jednej kolumny. Jeśli użyjesz dwóch kolumn, Twoje dane mogą wyglądać śmiesznie. Na przykład, jeśli użytkownik przechowuje

2013-09-04 | MONTH 
można się zastanawiać, dlaczego istnieje 4.

Ponownie, możesz otrzymać nieprawidłowy ciąg z moją sugestią.

Innym pomysłem jest wykonanie struny ISO 8601 Time intervals. Twój system bazy danych może mieć nawet typ przedziału czasowego.

+0

Problem z przechowywaniem ciągów znaków polega na tym, że nie można na nich łatwo wykonać arytmetyki, aby znaleźć liczbę miesięcy między 2013-08 a 2014-02, na przykład. Z drugiej strony nie można tego zrobić z większością innych alternatyw. –

Powiązane problemy