Algorytm ustalania transakcji między tygodniowymi seriami danych?

9

Próbuję opracować małe narzędzie do raportowania (z zapleczem sqlite). Mogę najlepiej opisać to narzędzie jako księgę „transakcji”. Staram się śledzić „transakcje” z cotygodniowego wyciągu danych:

  • „nowy” (lub dodaj) - zasób jest nowy w mojej aplikacji, ponieważ moja aplikacja mogła wcześniej nie śledzić tego zasobu, ponieważ nie był widziany za pomocą wyciągów.
  • „aktualizacja” (lub trafienie) - ostatnio korzystano z tego zasobu, aktualizowano okres przechowywania o kolejny tydzień.
  • „usuń” (lub upuść) - ten element nie przydał się od ostatniego raportu (opcjonalnie, ale byłoby miło mieć na wykresie zmiany zapotrzebowania na zasoby z tygodnia na tydzień).

Wszystko, co mam, to cotygodniowy ekstrakt danych (plik płaski rozdzielany potokami) pochodzący ze starszego systemu archiwizacji / zarządzania rekordami, nad którym nie mam kontroli.

Każda linia może być destylowana w celu:
resource_id | resource info | customer_id | customer_info

Przykładowe dane:

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

Celem jest ułatwienie raportowania zasobów, które nie były używane przez X miesięcy (na podstawie ostatniego trafienia). Istnieje okres przechowywania, w którym zasoby są przechowywane dla łatwego dostępu, jeśli są popularne. Zasób, który nie był używany przez 18 miesięcy, jest przeznaczony do długoterminowej archiwizacji w innym miejscu.

To musi być powszechny problem. Zastanawiasz się, czy istnieje algorytm ogólnego przeznaczenia do określania, co nowego / tego samego / usunięto między zestawami danych (db vs. najnowszy wyciąg)?

Swartz
źródło

Odpowiedzi:

1

Twoja odpowiedź brzmi ... Tak. Istnieje prosty algorytm, który można wdrożyć, który nie wymaga żadnych innych czynności. Jest to algorytm wartości bieżącej netto. Jest łatwy do wdrożenia i wszystko, czego wymaga po stronie bazy danych, to datowanie cotygodniowych danych i pisanie jednego prostego zapytania i jednej małej funkcji rekurencyjnej lub pętli, albo możesz wykonać jedno z tych innych rozwiązań.

NPV = PV- (PV (CP / T) lub Nowa wartość bieżąca równa jest wartości bieżącej razy bieżący okres (miesiące od ostatniego wpisu) podzielonej przez okres (np. 18 miesięcy), gdy wartość zasobu spada do 0, jest to wartość bieżąca netto jest wydatkowane.

Jeśli dasz mi język, w którym chcesz, opublikuję kod tutaj w edycji

J-Boss
źródło
Język nie jest tak ważny. Ruby lub C ++, gdybym musiał wybrać. Jeśli potrafisz napisać algorytm w HTML 4.0 Strict, będziesz moim bohaterem. Żartuję z tej ostatniej części :)
Swartz
Byłbym zainteresowany, aby zobaczyć kod. Ruby lub C ++. Dziękuję Ci.
Swartz
0

Jeśli i tak przechowujesz aktualizacje w zapleczu SQLite, możesz zamienić cotygodniową aktualizację w nową tabelę i porównać ją z danymi zarchiwizowanymi z zapytaniami przed scaleniem.

Przykład użycia SQL do znajdowania nowych dodatków do tabeli: /programming/2077807/sql-query-to-return-differences-between-two-tables

Jeśli pole w bazie danych DB zawiera datę transakcji, możesz po prostu zapytać wszystkich użytkowników, którzy mieli transakcje w ciągu ostatnich 18 miesięcy. Zatem archiwum jest po prostu pełną bazą danych. Alternatywnie możesz wysłać zapytanie do wszystkich użytkowników, którzy tego nie zrobili, wyodrębnić ich dane, a następnie upuścić. W tym tygodniu aktualizacje są oznaczone dowolnymi wierszami.

Davislor
źródło
Lepiej, jest to rozwiązanie przynajmniej zorientowane na dane, ale wciąż jest przesada
J-Boss,
Na razie używam sqlite, ponieważ łatwo jest zacząć. Można łatwo przejść do MySQL (lub PostgreSQL). Jeśli użycie backendu bez SQL przyniosłoby cokolwiek, co sprawiłoby, że ta praca działałaby jeszcze lepiej, to jestem w pełni usłuchany.
Swartz
Cóż, moje myślenie było przede wszystkim, że jesteś przekształcenie go do wierszy w bazie danych, w każdym razie . Jeśli nie musisz uruchamiać go jednocześnie z wielu procesów, nie sądzę, że chcesz przejść na coś cięższego niż SQLite.
Davislor,
Nie ma potrzeby równoczesnego przetwarzania. Ale muszę gdzieś przechowywać dane o zasobach. Baza danych SQL wydawała się dobrym wyborem, jednak nic nie stoi na przeszkodzie, aby ładować dane do dowolnego typu danych w celu przetworzenia delt. Na koniec każdego odcinka chcę tylko dowiedzieć się, co nowego, co pozostało takie samo, a co zniknęło. Na podstawie tych informacji mogę dowiedzieć się, jak zaktualizować rekordy.
Swartz
Po przeanalizowaniu danych i umieszczeniu ich w bazie danych, prawdopodobnie łatwiej jest napisać zapytanie niż zaimplementować algorytm. To powiedziawszy, jeśli chcesz go kodować, algorytm, który chcesz ustawić, jest różny i istnieje implementacja w C ++ STL, której możesz użyć, aby to zrobić w jednym wierszu po umieszczeniu obu zestawów danych w kontenerze twój wybór, prawdopodobnie a Vector.
Davislor,
0

Alternatywny pomysł:

  1. Przeanalizuj listę transakcji w jakąś strukturę danych, na przykład tablicę. (W C ++, pomyśl Vectori w Javie ArrayList.)

  2. Wykonaj zapytanie SQL backend na takie jak SELECT DISTINCT customer_id FROM Transactions ORDER BY customer_idi zapakować klasyfikowane odrębne identyfikatory klientów w zestawie old. Jeśli zrobisz dokładnie to samo z WHEREklauzulą ​​oddzielającą stare i nowe transakcje, możesz pominąć krok 3.

  3. Uzyskaj unikalne identyfikatory klientów z nowych aktualizacji w osobnej strukturze danych, w posortowanej kolejności. Istnieje kilka struktur danych można użyć, aby dostać się do struktury danych new. Wstawianie sortowania do podwójnie połączonej listy jest bardzo proste, ale użycie pośredniej tablicy haszującej działałoby w czasie zbliżonym do liniowego, lub jeśli i tak sortujesz oryginalną tablicę, uzyskanie zestawu jest łatwe.

  4. Weź różnicę new- oldkorzystając ze standardowej biblioteki swojego ulubionego języka. Twój ulubiony język ma ten algorytm w swojej standardowej bibliotece?

Inne rzeczy, które chcesz zrobić, to na pewno zapytania SQL po zaktualizowaniu bazy danych transakcji.

Uwaga do kroku 3: Rozważ naturę swoich danych. Załóżmy, że Twój plik tekstowy wyświetla zamówienia chronologicznie, aw typowym tygodniu jest wielu klientów, którzy po raz pierwszy otrzymali nowe customer_idw kolejności rosnącej. Załóżmy, że większość innych zamówień pochodzi od niewielkiej liczby lojalnych stałych klientów, z niższymi customer_id. Twoje dane wejściowe są już w większości posortowane. Rodzaj wstawiania, w którym próbujesz wstawiać nisko customer_idna początku podwójnie połączonej listy i wysoko customer_idna tyle, w tej sytuacji sprawdziłby się w praktyce.

Davislor
źródło
1
Bardziej interesują mnie nowe / te same / zaktualizowane zasoby niż klienci. Ale tak, pomysł byłby taki sam.
Swartz
0

Jak rozumiem z twojego pytania, faktycznie masz identyfikator_zasobu (+ informacje) i „listę” klienta (identyfikator + informacje).

Dzięki temu możesz łatwo przechowywać listę klientów według zasobów i sprawdzać ostatni węzeł na każdej liście w zasobie (aby poznać czas ostatniej operacji; wystarczy dodać pole daty do klienta w kodzie)

Nie znam SQL, dlatego podaję przykład HashMapi List, ale jestem pewien, że to ten sam pomysł: HashMap <Resource, List<Customer>>kiedy Resourcepowinien zawierać Customeridentyfikator zasobu jako klucz i powinien zawierać identyfikator klienta, informacje i datę operacji.

Dzięki temu pomysłowi możesz łatwo poznać czas ostatniej operacji i modyfikować dowolny zasób (dodaj \ usuń zasób \ klienta).

AsfK
źródło
0

Jeśli korzystasz z bazy danych SqLite, jeśli dodasz datę partii również jako kolumnę tabeli,

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

dość łatwo byłoby użyć SQL, aby uzyskać zasoby nieużywane w ciągu ostatnich X dni

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

Nie przetestowałem SQL, ale powinien dać ci pomysł

Nisko latający pelikan
źródło
0

Z oryginalnego postu wygląda na to, że przetwarzane dane nie mają pola wskazującego datę / godzinę transakcji, i zakładam, że plik jest przyjmowany często zgodnie z harmonogramem, takim jak dzienny, godzinowy itp.

Poradziłbym sobie z tym, dodając kolumnę znacznika czasu SQL, która jest albo automatycznie generowana na poziomie bazy danych, albo przez kod, który wyodrębnia dane i wstawia do bazy danych. Następnie umieść indeks w tej kolumnie znacznika czasu i gotowe. Pozwól silnikowi DB wykonać zadanie polegające na tym, aby skutecznie odpowiedzieć na pytanie „ile transakcji się nie wydarzyło od tego czasu” lub „ile transakcji od tego czasu do tego czasu”.

Następnie zaplanujesz zadanie, aby wykonać zapytanie i obliczyć różnice, które chcesz zgłosić. Transakcje, które są „nowe”, to transakcje, które nie mają żadnych rekordów w bazie danych przed datą zapytania o „nową od”. Stare rekordy to te, które nie zawierają transakcji od daty granicznej.

Thomas Carlisle
źródło
-2

Czy nie po to są HashTables? Jeśli wszystko, co chcesz zrobić, to prowadzić ewidencję zasobów używanych w ostatnich miesiącach i usuwać zasoby, do których nie uzyskano dostępu w ciągu ostatnich 18 miesięcy, możesz użyć tabeli HashTable, w której kluczem jest id_zasobu, a wartością jest data ostatniego dostępu.

Aby zarchiwizować rekordy> 18 miesięcy, możesz przejrzeć wszystkie rekordy w tabeli skrótów i po prostu usunąć (lub przenieść) te konkretne rekordy. (możesz to robić co tydzień, gdy pojawi się raport)

Adrian Buzea
źródło
Dlaczego potrzebuję HashTable, jeśli przechowuję rzeczy w bazie danych? Mogę robić aktualizacje rekordów db. Bardziej interesuje mnie sprawa: weź dwa zestawy danych, znajdź różnice (co zostało dodane, pozostaje takie samo, usunięte) między dwoma zestawami. W jaki sposób technika HashTable pomogłaby znaleźć nowe i „usunięte” rekordy?
Swartz
Jeśli tabele są indeksowane w bazie danych, to w zasadzie są to także HashTables za kulisami. Jeśli masz 2 tabele, z których każda reprezentuje zestaw danych, możesz uzyskać nowe i usunięte rekordy, wykonując kilka połączeń zewnętrznych. Zobacz to w celach informacyjnych: i.stack.imgur.com/pxUO3.png . Upewnij się, że masz indeksy w kolumnie resource_id i powinno to być dość szybkie. Jeśli musiałbyś zaimplementować to od zera, myślę, że HashTables nadal będzie dobrym rozwiązaniem, ponieważ możesz wyszukiwać / wstawiać / usuwać w zamortyzowanym czasie O (1). Nie mogę wymyślić bardziej wydajnego sposobu na zrobienie tego.
Adrian Buzea
3
Istnieją lepsze struktury danych, które radzą sobie ze starzeniem się bez dodatkowych kroków wbijania tego w tablicę skrótów.
Chcesz wspomnieć o niektórych?
Adrian Buzea
@Snowman - Chciałbym móc jeszcze raz to ocenić, po prostu zdecydowanie zaakceptuję ten komentarz
J-Boss