Algorithmus zur Bestimmung von Transaktionen zwischen wöchentlichen Datenreihen?


9

Ich versuche, ein kleines Berichterstellungstool (mit SQLite-Backend) zu entwickeln. Ich kann dieses Tool am besten als "Transaktions" -Buch beschreiben. Ich versuche, "Transaktionen" aus dem wöchentlichen Datenextrakt zu verfolgen:

  • "neu" (oder hinzufügen) - Die Ressource ist neu in meiner App, da meine App diese Ressource möglicherweise noch nicht verfolgt hat, da sie nicht über Auszüge angezeigt wurde .
  • "Update" (oder Treffer) - Diese Ressource wurde kürzlich verwendet. Die Aufbewahrungsdauer wird um eine weitere Woche aktualisiert.
  • "Löschen" (oder Löschen) - Dieses Element wurde seit dem letzten Bericht nicht mehr verwendet (optional, wäre aber hilfreich, um Änderungen des Ressourcenbedarfs von Woche zu Woche grafisch darzustellen).

Alles, was ich habe, ist ein wöchentlicher Datenextrakt (durch Pipe getrennte Flatfile), der aus einem alten Archivierungs- / Datensatzverwaltungssystem stammt, über das ich keine Kontrolle habe.

Jede Linie kann grundsätzlich folgendermaßen destilliert werden:
resource_id | resource info | customer_id | customer_info

Beispieldaten:

10| Title X       | 1 | Bob
11| Another title | 1 | Bob
10| Title X       | 2 | Alice

Ziel ist es, die Berichterstattung über Ressourcen zu vereinfachen, die seit X Monaten nicht mehr verwendet wurden (basierend auf dem letzten Treffer). Es gibt eine Aufbewahrungsfrist, in der Ressourcen für einen einfachen Zugriff aufbewahrt werden, wenn sie beliebt sind. Eine Ressource, die seit 18 Monaten nicht mehr verwendet wird, ist für die langfristige Archivierung an anderer Stelle gekennzeichnet.

Dies muss ein häufiges Problem sein. Sie fragen sich, ob es einen Allzweckalgorithmus gibt, mit dem ermittelt werden kann, was zwischen Datensätzen neu / gleich / entfernt ist (Datenbank vs. letzter Auszug)?

Antworten:


1

Nun, Ihre Antwort lautet ... Ja. Es gibt einen einfachen Algorithmus, den Sie implementieren können, für den nichts anderes erforderlich ist. Es ist ein Barwertalgorithmus. Es ist einfach zu implementieren und alles, was es auf der DB-Seite erfordert, ist, dass Sie die wöchentlichen Daten mit einem Datumsstempel versehen und eine einfache Abfrage und eine kleine rekursive Funktion oder eine for-Schleife schreiben, oder Sie könnten eine dieser anderen Lösungen ausführen.

NPV = PV- (PV (CP / T) oder der neue Barwert entspricht dem Barwert multipliziert mit der aktuellen Periode (Monate seit dem letzten Eintrag) geteilt durch die Laufzeit (z. B. 18 Monate), wenn der Ressourcenwert auf 0 fällt, seinen Barwert wird ausgegeben.

Wenn Sie mir eine Sprache geben, in der Sie sie haben möchten, werde ich den Code hier in einer Bearbeitung veröffentlichen


Sprache ist nicht so wichtig. Ruby oder C ++, wenn ich mich entscheiden musste. Wenn Sie einen Algorithmus in HTML 4.0 Strict schreiben können, werden Sie mein Held sein. Scherz über diesen letzten Teil :)
Swartz

Würde mich interessieren den Code zu sehen. Ruby oder C ++. Vielen Dank.
Swartz

0

Wenn Sie die Aktualisierungen trotzdem in einem SQLite-Backend aufbewahren, können Sie die wöchentliche Aktualisierung in eine neue Tabelle umwandeln und sie mit Abfragen mit den archivierten Daten vergleichen, bevor Sie sie zusammenführen.

Beispiel für die Verwendung von SQL zum Suchen neuer Ergänzungen zu einer Tabelle: /programming/2077807/sql-query-to-return-differences-between-two-tables

Wenn in einem Feld in Ihrer Datenbank das Datum der Transaktion gespeichert ist, können Sie einfach alle Benutzer abfragen, die in den letzten 18 Monaten Transaktionen durchgeführt haben. Dann ist das Archiv nur die vollständige Datenbank. Alternativ können Sie alle Benutzer abfragen, die dies nicht getan haben, ihre Daten extrahieren und sie dann löschen. Updates sind nur beliebige Zeilen, die diese Woche mit einem Zeitstempel versehen wurden.


Besser, es ist zumindest eine datenzentrierte Lösung, aber es ist immer noch übertrieben
J-Boss

Ich benutze vorerst ein SQLite, da es einfach zu beginnen ist. Könnte leicht zu MySQL (oder PostgreSQL) wechseln. Wenn die Verwendung eines No-SQL-Backends irgendetwas netto machen würde, um diese Arbeit noch besser zu machen, bin ich ganz Ohr.
Swartz

Nun, ich dachte hauptsächlich, dass Sie es sowieso in Zeilen in einer Datenbank konvertieren . Wenn Sie es nicht von mehreren Prozessen gleichzeitig ausführen müssen, möchten Sie wahrscheinlich nicht zu etwas Schwerem als SQLite wechseln.
Davislor

Keine gleichzeitige Verarbeitung erforderlich. Aber ich muss die Daten über Ressourcen irgendwo speichern. Eine SQL-Datenbank schien eine gute Wahl zu sein. Nichts hindert mich jedoch daran, Daten in einen Datentyp für die Verarbeitung von Deltas zu laden. Alles, was ich am Ende jedes Extraktlaufs möchte, ist herauszufinden, was neu ist, was gleich geblieben ist und was verschwunden ist. Anhand dieser Informationen kann ich herausfinden, wie Datensätze nach Bedarf aktualisiert werden können.
Swartz

Nachdem Sie die Daten analysiert und in die Datenbank gestellt haben, ist es wahrscheinlich einfacher, eine Abfrage zu schreiben, als einen Algorithmus zu implementieren. Das heißt, wenn Sie es codieren möchten, ist der gewünschte Algorithmus ein festgelegter Unterschied, und es gibt eine Implementierung in der C ++ - STL, mit der Sie dies in einer einzelnen Zeile tun können, sobald Sie beide Datensätze in den Container von gestellt haben Ihre Wahl, wahrscheinlich a Vector.
Davislor

0

Alternative Idee:

  1. Analysieren Sie Ihre Liste von Transaktionen in eine Art Datenstruktur, z. B. ein Array. (Denken Sie in C ++ Vectorund in Java ArrayList.)

  2. Führen Sie eine Abfrage in Ihrem SQL-Backend durch, z. B. SELECT DISTINCT customer_id FROM Transactions ORDER BY customer_idund packen Sie die sortierten unterschiedlichen Kunden-IDs in einen Satz old. Wenn Sie genau dasselbe mit einer WHEREKlausel tun, die die alten und neuen Transaktionen trennt, können Sie Schritt 3 überspringen.

  3. Holen Sie sich die eindeutigen Kunden-IDs aus den neuen Updates in sortierter Reihenfolge in eine separate Datenstruktur. Es gibt einige Datenstrukturen, mit denen Sie eine Datenstruktur erstellen können new. Das Einfügen einer Sortierung in eine doppelt verknüpfte Liste ist sehr einfach, aber die Verwendung einer Zwischen-Hashtabelle würde in nahezu linearer Zeit ausgeführt. Wenn Sie das ursprüngliche Array trotzdem sortieren, ist es einfach, daraus einen Satz zu erstellen.

  4. Nehmen Sie den eingestellten Unterschied new- oldverwenden Sie die Standardbibliothek Ihrer Lieblingssprache. Ihre Lieblingssprache hat diesen Algorithmus in ihrer Standardbibliothek?

Die anderen Dinge, die Sie tun möchten, sind definitiv SQL-Abfragen, nachdem Sie Ihre Transaktionsdatenbank aktualisiert haben.

Hinweis zu Schritt 3: Berücksichtigen Sie die Art Ihrer Daten. Angenommen, Ihre Textdatei listet Bestellungen chronologisch auf, und in einer typischen Woche gibt es viele Erstkunden, die eine neue customer_idin aufsteigender Reihenfolge erhalten. Angenommen, die meisten anderen Bestellungen stammen von einer kleinen Anzahl treuer Stammkunden mit weniger customer_id. Dann sind Ihre Eingaben bereits größtenteils sortiert. Eine Einfügungssortierung, bei der Sie versuchen, am Anfang customer_ideiner doppelt verknüpften Liste niedrig und customer_idhinten hoch einzufügen, würde in dieser Situation in der Praxis gut funktionieren.


1
Ich interessiere mich mehr für die neuen / gleichen / aktualisierten Ressourcen als für Kunden. Aber ja, die Idee wäre dieselbe.
Swartz

0

Wie ich aus Ihrer Frage verstehe, haben Sie tatsächlich resource_id (+ info) und "Liste" des Kunden (id + info).

So können Sie auf einfache Weise die Kundenliste pro Ressource führen und den letzten Knoten in jeder Liste der Ressource überprüfen (um die letzte Betriebszeit zu ermitteln; Sie müssen Ihrem Kunden nur ein Datumsfeld im Code hinzufügen).

Ich bin nicht mit SQL vertraut, daher gebe ich mein Beispiel mit HashMapund List an, aber ich bin mir sicher, dass es dieselbe Idee ist: HashMap <Resource, List<Customer>>Wann Resourcesollte die Ressourcen- CustomerID als Schlüssel und die Kunden-ID, Informationen und das Betriebsdatum enthalten.

Mit dieser Idee können Sie die letzte Betriebszeit leicht ermitteln und jede Ressource ändern (Ressource hinzufügen / entfernen \ Kunde).


0

Wenn Sie eine SqLite-Datenbank verwenden und das Datum des Stapels auch als Spalte der Tabelle hinzufügen,

10| Title X       | 1 | Bob    | 2015-03-01
11| Another title | 1 | Bob    | 2015-03-01
...............................
10| Title X       | 1 | Alice  | 2015-03-05

Es wäre ziemlich einfach, eine SQL zu verwenden, um die Ressourcen zu erhalten, die in den letzten X Tagen nicht verwendet wurden

Select distinct r.ResourceID from Resources r
where not exists (SELECT julianday('now') - julianday(r.DateUpdated)) < X

Ich habe SQL nicht getestet, aber es sollte Ihnen eine Idee geben


0

Aus dem ursprünglichen Beitrag geht hervor, dass die aufgenommenen Daten kein Feld zur Angabe des Datums / der Uhrzeit der Transaktion enthalten. Ich gehe davon aus, dass die Datei häufig nach einem Zeitplan wie täglich, stündlich usw. aufgenommen wird.

Ich würde dies behandeln, indem ich eine SQL-Zeitstempelspalte hinzufüge, die entweder auf Datenbankebene automatisch generiert wird, oder durch den Code, der die Daten extrahiert und in die Datenbank einfügt. Dann setzen Sie einen Index auf diese Zeitstempelspalte und fertig. Lassen Sie die DB-Engine die Frage effizient erledigen, wie viele Transaktionen seit diesem Zeitpunkt nicht mehr stattgefunden haben oder wie viele zwischen diesem Zeitpunkt und diesem Zeitpunkt.

Anschließend planen Sie einen Job zum Abfragen und Berechnen der Differentiale, über die Sie Bericht erstatten möchten. Transaktionen, die "neu" sind, sind Transaktionen, die vor dem Datum, an dem Sie "neu seit" fragen, keine Datensätze in der Datenbank haben. Alte Datensätze sind solche, die seit dem Stichtag keine Transaktionen mehr haben.


-2

Ist das nicht was HashTables sind? Wenn Sie lediglich Aufzeichnungen darüber führen möchten, welche Ressourcen in den letzten Monaten verwendet wurden, und Ressourcen löschen, auf die in den letzten 18 Monaten nicht zugegriffen wurde, können Sie eine HashTable verwenden, bei der der Schlüssel die resource_id und der Wert der ist letztes Zugriffsdatum.

Um die Datensätze für mehr als 18 Monate zu archivieren, können Sie alle Datensätze in der Hash-Tabelle durchgehen und diese spezifischen Datensätze einfach entfernen (oder verschieben). (Sie können dies wöchentlich tun, wenn der Bericht eingeht.)


Warum wird HashTable benötigt, wenn ich Inhalte in der Datenbank speichere? Ich kann Aktualisierungen an DB-Datensätzen vornehmen. Ich interessiere mich mehr für einen Fall: Nehmen Sie zwei Datensätze, finden Sie die Unterschiede (was hinzugefügt wurde, bleibt gleich, gelöscht) zwischen den beiden Sätzen heraus. Wie würde eine HashTable-Technik beim Auffinden neuer und "entfernter" Datensätze helfen?
Swartz

Wenn die Tabellen in der Datenbank indiziert sind, sind sie im Grunde auch HashTables hinter den Kulissen. Wenn Sie zwei Tabellen haben, die jeweils einen Datensatz darstellen, können Sie Ihre neuen und entfernten Datensätze durch einige äußere Verknüpfungen abrufen. Siehe dies als Referenz: i.stack.imgur.com/pxUO3.png . Stellen Sie sicher, dass Sie Indizes für die Spalte resource_id haben und diese sollte ziemlich schnell sein. Wenn Sie dies von Grund auf neu implementieren müssten, wäre HashTables meiner Meinung nach immer noch der richtige Weg, da Sie in O (1) amortisierter Zeit nachschlagen / einfügen / löschen können. Ich kann mir keinen effizienteren Weg vorstellen, dies zu tun.
Adrian Buzea

3
Es gibt bessere Datenstrukturen, die das Altern handhaben, ohne die zusätzlichen Schritte, um dies in eine Hash-Tabelle zu packen.

Möchtest du einige erwähnen?
Adrian Buzea

@Snowman - Ich wünschte, ich könnte das noch ein paar Mal bewerten, ich werde diesem Kommentar nur nachdrücklich zustimmen
J-Boss
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.