Dies ist ein Problem, auf das ich einige Male gestoßen bin. Stellen Sie sich vor, Sie haben einen Datensatz, den Sie in einer Datenbanktabelle speichern möchten. Diese Tabelle enthält eine DateTime-Spalte mit dem Namen "date_created". Dieser eine Datensatz wurde vor langer Zeit erstellt, und Sie sind sich nicht sicher, wann er genau sein soll, aber Sie kennen Jahr und Monat. Andere Aufzeichnungen kennen Sie nur das Jahr. Andere Aufzeichnungen kennen Sie den Tag, den Monat und das Jahr.
Sie können kein DateTime-Feld verwenden, da "Mai 1978" kein gültiges Datum ist. Wenn Sie es in mehrere Spalten aufteilen, verlieren Sie die Abfragefähigkeit. Hat jemand anderes darauf gestoßen, wenn ja, wie sind Sie damit umgegangen?
Um das von mir erstellte System zu verdeutlichen, handelt es sich um ein System, das Archive verfolgt. Einige Inhalte wurden vor langer Zeit produziert und alles was wir wissen ist "Mai 1978". Ich könnte es als 1. Mai 1978 speichern, aber nur mit einem Hinweis darauf, dass dieses Datum nur auf den Monat genau ist. Auf diese Weise bin ich einige Jahre später beim Abrufen dieses Archivs nicht verwirrt, wenn die Daten nicht übereinstimmen.
Für meine Zwecke ist es wichtig, den "unbekannten Tag im Mai 1978" vom "1. Mai 1978" zu unterscheiden. Außerdem möchte ich die Unbekannten nicht als 0 speichern, wie zum Beispiel "May 0, 1978", da die meisten Datenbanksysteme dies als ungültigen Datumswert ablehnen.
quelle
Antworten:
Speichern Sie alle Daten im normalen DATE-Feld in der Datenbank und geben Sie zusätzlich an, wie genau das DATE-Feld tatsächlich ist.
Erstellungsdatum_genauigkeit: 1 = genaues Datum, 2 = Monat, 3 = Jahr.
Wenn Ihr Datum unscharf ist (z. B. Mai 1980), speichern Sie es zu Beginn des Zeitraums (z. B. 1. Mai 1980). Oder wenn Ihr Datum auf das Jahr (zB 1980) genau ist, speichern Sie es als 1. Januar. 1980 mit entsprechendem Genauigkeitswert.
Auf diese Weise können Sie leicht auf eine etwas natürliche Weise abfragen und wissen immer noch, wie genau die Daten sind. Auf diese Weise können Sie beispielsweise Daten zwischen
Jan 1st 1980
und abfragenFeb 28th 1981
und unscharfe Daten1980
und abrufenMay 1980
.quelle
select * from mytable where date_created between "1980/1/1" and "1981/2/28" and date_created_accuracy <= 2;
. Genius.date_created_accuracy
. Sie können "Mai 1980" oder nur "1980" in den Ergebnissen oder in der Benutzeroberfläche anzeigen, wenn dies so genau ist, wie es das Feld angibt.Wenn Sie diese Art von Daten nicht als reguläre Datums- / Uhrzeitinformationen verwenden müssen, ist ein einfaches Zeichenfolgenformat ausreichend.
Wenn Sie jedoch die gesamte Funktionalität beibehalten müssen, kann ich mir zwei Problemumgehungen vorstellen, die beide zusätzliche Informationen erfordern, die in der Datenbank gespeichert sind:
min date
undmax date
Felder, die unterschiedliche Werte für "unvollständige" Daten haben, aber für genaue Daten übereinstimmen.type
den Datensätzen ein Feld hinzu, und behalten Sie bei, welche Informationen fehlen.quelle
min date
undmax date
Felder. Ich denke, das ist die flexibelste, aber genaueste und benutzerfreundlichste Lösung.Dies ist eher eine Anforderungsdefinition als ein technisches Problem. Sie müssen sich auf die Frage konzentrieren, "wie wir die Daten in der Vergangenheit definieren können" und die technische Lösung wird fließen.
Die Zeiten, in denen ich mich so etwas nähern musste, haben wir normalerweise:
Manchmal muss man so etwas tun, wie die Daten unscharf zu machen - zum Beispiel, dass ein Datum möglicherweise im Mai 1978 auf eine Anfrage nach irgendetwas antworten muss Die Tage verteilen sich entsprechend, neue erhalten 2 identische Werte.
quelle
Der einfachste Weg, um anzuzeigen, ob das Datum korrekt ist, besteht darin, ein Genauigkeitsfeld INT (1) mit dem Standardwert NULL zu erstellen
Wenn das Datum korrekt ist, speichern Sie die Datums- / Uhrzeitangabe in "date_created" und lassen Sie die Genauigkeit NULL
Wenn das Datum nur auf den Monat genau ist, speichern Sie Datum und Uhrzeit als 1. des Monats mit dem Genauigkeitswert 1
Wenn das Datum nur für das Jahr korrekt ist, speichern Sie das Datum und die Uhrzeit am 1. Januar mit dem Genauigkeitswert 2
Sie können verschiedene Zahlen verwenden, um verschiedene Werte wie das erste Quartal usw. Zu speichern
quelle
In der Vergangenheit habe ich Datumsangaben mit Genauigkeit als Start- und Enddatum gespeichert. Der Tag 21.05.2012 würde als Start = 12.00 Uhr, 21.05.2012 und Ende = 12.00 Uhr, 22.05.2012 dargestellt. Das Jahr 2012 wird als Start = 12.00 Uhr, 1. Januar 2012 und Ende = 12.00 Uhr, 1. Januar 2013 dargestellt.
Ich bin mir nicht sicher, ob ich diesen Ansatz empfehlen würde. Wenn Sie dem Benutzer die Informationen anzeigen, müssen Sie richtig erkennen, dass ein Datumsbereich genau einen Tag abdeckt, um "25. Mai" anstelle von zwei überbestimmten Endpunkten anzuzeigen (was bedeutet, dass Sie sich mit Sommerzeit usw. befassen müssen).
Wenn Sie jedoch nicht versuchen, in eine menschliche Sprache zu übersetzen, ist das Programmieren mit den Endpunkten viel einfacher als mit der Genauigkeit von center +. Sie haben nicht viele Fälle. Das ist ziemlich nett.
quelle
Warum nicht zwei Daten speichern.
Created_After und Created_Before. Die eigentliche Semantik wird "erstellt am oder nach" und "erstellt am oder vor"
Wenn Sie also das genaue Datum kennen, sind Created_After und Created_Before dasselbe Datum.
Wenn Sie wissen, dass es die erste Woche im Mai 2000 war, sind Created_After = '2000-05-01' und Created_Before = '2000-05-07'.
Wenn Sie nur den Mai 1999 kennen, sind die Werte '1999-05-01' und '1999-05-30'.
Wenn es "Summer of '42" ist, lauten die Werte "1942-06-01" und "1942-08-31".
Dieses Schema ist mit normalem SQL einfach abzufragen und für einen nicht technischen Benutzer recht einfach zu befolgen.
So finden Sie beispielsweise alle Dokumente, die möglicherweise im Mai 2001 erstellt wurden:
Umgekehrt finden Sie alle Dokumente, die definitiv im Mai 2001 erstellt wurden:
quelle
Das Datums- und Uhrzeitformat nach ISO 8601 wird mit einer Definition der Dauer geliefert, z
2012-01-01P1M
(lesen Sie: 2012, 1. Januar, Zeitraum: 1 Monat) ist das, was "im Januar 2012" sein sollte.Ich würde dies verwenden, um die Daten zu speichern . Möglicherweise benötigen Sie dazu ein Datenbankfeld vom Typ String. Es ist ein anderes Thema, wie man eine vernünftige Suche danach durchführt.
quelle
Im Allgemeinen speichere ich sie immer noch als Datum für allgemeine Abfragen. Dies ist immer noch möglich, auch wenn dies etwas weniger genau ist.
Wenn es wichtig ist, die Genauigkeit zu kennen, habe ich in der Vergangenheit entweder ein Genauigkeits- "Fenster" als +/- Dezimalzahl oder als Nachschlag (Tag, Monat, Jahr usw.) gespeichert. In anderen Fällen speichere ich anstelle des Fensters nur den ursprünglichen Datumswert als Zeichenfolge und konvertiere, was ich kann, in eine Datums- / Uhrzeitangabe, möglicherweise 1978-05-01 00:00:00 und "Mai 1978" für Ihr gegebenes Beispiel.
quelle
Sagt wer? Folgendes machst du:
Wenn ich also ein Insert wie:
insert into thistable (Day, Month, Year) values (-1, 2, 2012);
mache, wird TheDate zum 01.02.2013, aber ich weiß, dass das Datum in 2/2012 wirklich unbestimmt ist, da im Feld „-1“ ein Tag steht.Wenn ich
insert into thistable (TheDate) values ('2/5/2012');
dann Tag 5 bin , Monat 2 ist und Jahr 2012 ist und weil keiner von ihnen -1 ist, weiß ich, dass dies das genaue Datum ist.Ich verliere nicht die Fähigkeit zur Abfrage, da der Einfüge- / Aktualisierungs-Trigger sicherstellt, dass meine 3 Felder (Tag, Monat, Jahr) immer einen DateTime-Wert in TheDate erzeugen, der abgefragt werden kann.
quelle
Eine andere Möglichkeit wäre, die Daten als ganze Zahlen des Formulars zu speichern
YYYYMMDD
.19510000
19510300
19510314
0
Leistungen
Sie können Ihr unscharfes Datum in einem Feld anstelle von zwei Datumsfeldern oder einem Datum und einer Genauigkeit speichern, wie in vielen anderen Antworten vorgeschlagen.
Fragen sind immer noch einfach:
SELECT * FROM table WHERE thedate>=19510000 and thedate<19520000
SELECT * FROM table where thedate>=19510300 and thedate<19510400
SELECT * FROM table where thedate=19510314
ANMERKUNGEN
GetDateString(int fuzzyDate)
die ziemlich einfach zu implementieren ist.99
anstelle des00
Monats oder des Tages das Auffüllen verwenden .quelle
ISO 8601 spezifiziert auch eine Syntax für "Fuzzy-Daten". 12. Februar 2012 um 15 Uhr wäre "2012-02-12T15" und Februar 2012 könnte einfach "2012-02" sein. Dies lässt sich mit der lexikografischen Standardsortierung gut erweitern:
quelle
Hier ist meine Meinung dazu:
Vom unscharfen Datum zum Datum / Uhrzeit-Objekt wechseln (das in eine Datenbank passt)
Und dann eine Funktion, die das datetime-Objekt aufnimmt und es in ein unscharfes Datum zurückverschiebt.
Und dann ein Unit Test. Habe ich irgendwelche Fälle verpasst?
Es gibt einen Eckfall, in dem ein Ereignis, das zwar genau
2001-01-01T00:00:00.333333
zum Zeitpunkt des Ereignisses eingetreten ist , vom System jedoch nur als "2001" interpretiert wird, dies jedoch sehr unwahrscheinlich erscheint.quelle
Ich arbeite für einen Verlag, der sich mit vielen alten Büchern beschäftigt, bei denen wir oft nicht die genauen Daten für die Dinge bekommen. Wir haben normalerweise zwei Felder für einen bestimmten Datumseintrag, das Datum und einen circa- Booleschen Wert:
Wir verwenden das Datumsfeld, um das Datum eines Ereignisses anzugeben, oder ein Datum, das "nah genug" ist, falls wir das wahre Datum nicht kennen. Für den Fall, dass wir das wahre Datum nicht kennen, markieren wir das
dateCirca
Feld alsY
und geben ein Datum an, das nah genug ist und als "1." gekennzeichnet ist, wie zquelle
Überblick
Es gibt viele mögliche Darstellungen und damit Datenbankschemata zum Speichern von unscharfen Datums- und Uhrzeitangaben (oder auch nur unscharfen Datumsangaben):
[1], [2] und [3] sind alle (implizit) einheitliche Intervalle, dh eine Menge von (gleich) möglichen Zeitpunkten.
[4] ist am ausdrucksstärksten, dh wenn mögliche (oder zumindest willkürlich lange) geschriebene Sprachsätze oder -phrasen zugelassen werden. Aber es ist auch am schwierigsten, damit zu arbeiten. Im Grenzfall müsste AI auf menschlicher Ebene mit beliebigen Werten umgehen. In der Praxis müsste der Bereich möglicher Werte stark eingeschränkt werden, und alternative "strukturierte" Werte wären wahrscheinlich für viele Operationen, z. B. Sortieren, Suchen, vorzuziehen.
[5] ist wahrscheinlich die allgemeinste kompakte Darstellung, die (etwas) praktisch ist.
Einheitliche Intervalle
Einheitliche Intervalle sind die einfachste kompakte Möglichkeit, eine Reihe von (möglichen) Datums- / Uhrzeitwerten darzustellen.
Bei [1] werden Teile des Datum-Uhrzeit-Werts ignoriert, dh die Teile, die Einheiten entsprechen, die feiner als die angegebene Genauigkeit oder Genauigkeit sind. Andernfalls entspricht dies [2], und der Genauigkeitscode entspricht einem Intervall mit denselben Einheiten (und einer implizierten Menge von 1).
[2] und [3] sind ausdrücklich gleichwertig. [1] ist strikt weniger aussagekräftig als beide, da es effektive Intervalle gibt, die nicht durch [1] dargestellt werden können, z. Eine unscharfe Datums- / Uhrzeitangabe, die einem 12-Stunden-Intervall entspricht, das sich über eine Datumsgrenze erstreckt.
[1] ist für Benutzer einfacher einzugeben als jede andere Darstellung und sollte im Allgemeinen (zumindest geringfügig) weniger Eingaben erfordern. Wenn Datums- und Uhrzeitangaben in verschiedenen Textdarstellungen eingegeben werden können, z. B. "2013", "2014-3", "2015-5-2", "7/30/2016 11p", "2016-07-31 18:15" kann die Präzision oder Genauigkeit auch automatisch aus der Eingabe abgeleitet werden.
Die Genauigkeit oder Präzision von [1] ist auch am einfachsten in ein Formular umzuwandeln, das den Benutzern übermittelt werden soll, z. (Beachten Sie, dass letztere sowieso nicht durch [1] dargestellt werden können).
Streicher
In der Praxis müssen Zeichenfolgenwerte in andere Darstellungen konvertiert werden, um mehrere Werte abzufragen, zu sortieren oder auf andere Weise zu vergleichen. Während also jede geschriebene natürliche (menschliche) Sprache strikt aussagekräftiger ist als [1], [2], [3] oder [5], verfügen wir noch nicht über die Mittel, um weit über Standardtextdarstellungen oder -formate hinauszugehen. Angesichts dessen ist dies wahrscheinlich die am wenigsten nützliche Darstellung für sich .
Ein Vorteil dieser Darstellung ist, dass Werte in der Praxis für Benutzer so wie sie sind darstellbar sein sollten und keine Transformation erfordern, um leicht verständlich zu sein.
Wahrscheinlichkeitsverteilungen
Wahrscheinlichkeitsverteilungen verallgemeinern die einheitlichen Intervalldarstellungen [1], [2], [3] und sind (wohl) der (allgemeinen) Zeichenfolgendarstellung [4] äquivalent.
Ein Vorteil von Wahrscheinlichkeitsverteilungen gegenüber Zeichenfolgen besteht darin, dass erstere eindeutig sind.
[5-1] ist für Werte geeignet, die (meistens) mit einer vorhandenen Verteilung übereinstimmen, z. B. ein Datums- / Zeitwert, der von einem Gerät ausgegeben wird, für das bekannt ist, dass Messungen mit einer bestimmten Verteilung übereinstimmen (oder angenommen werden).
[5-2] ist wahrscheinlich die beste (etwas) praktische Möglichkeit, beliebige "Fuzzy-Datetime" -Werte kompakt darzustellen. Natürlich ist die Berechenbarkeit der verwendeten spezifischen Wahrscheinlichkeitsverteilungen von Bedeutung und es gibt definitiv interessante (und möglicherweise unmögliche) Probleme, die beim Abfragen, Sortieren oder Vergleichen verschiedener Werte zu lösen sind, aber vieles davon ist wahrscheinlich bereits bekannt oder irgendwo in der vorhandenen gelöst Die mathematische und statistische Literatur steht also definitiv für eine äußerst allgemeine und eindeutige Darstellung.
quelle
Die Lösung von James Anderson gefällt mir sehr gut. Durch genaues Eingrenzen der Daten erhalten Sie die flexibelste Abfragestruktur. Eine andere Möglichkeit, dies zu erreichen, ist die Verwendung eines Start-, End- oder sogar eines Zentrums
date
plus einesinterval
(zumindest in PostgreSQL , Oracle und SQLAlchemy verfügbar ).quelle
In deinem Fall brauchst du nur Jahr, Monat und Tag. Jahr und Monat sind erforderlich, Tag ist optional. Ich würde so etwas benutzen:
Außerdem können Sie Indizes immer noch sehr effektiv verwenden. Die (tiny = minus, queires werden etwas "komplizierter" (länger).
quelle
1978-??-31
?Ich würde einfach die genaue Zeit für normale Daten speichern und den Zeitanteil des Fuzzy-Datums generisch auf 00:00:00 setzen. Ich würde dann alle unscharfen Daten zum 1. des Monats machen.
Wenn Sie abfragen, Sie
Es gibt bessere Lösungen als diese, aber ich persönlich hasse Metadaten (Daten über meine Daten). Es hat nur die Angewohnheit, nach einer Weile außer Kontrolle zu geraten.
quelle