web-dev-qa-db-ja.com

週次データシリーズ間のトランザクションを決定するためのアルゴリズム?

私は小さなレポートツール(sqliteバックエンド)を開発しようとしています。このツールは「トランザクション」元帳として最もよく説明できます。私がやろうとしていることは、毎週のデータ抽出からの「トランザクション」を追跡することです。

  • 「新規」(または追加)-私のアプリはこのアプリにとって新しいリソースですnot以前はこのリソースを抽出によって確認されていないため、追跡している可能性があります。
  • 「更新」(またはヒット)-そのリソースが最近使用され、保存期間がもう1週間更新されます。
  • "削除"(または削除)-このアイテムは、前回のレポート以降、使用されていません(オプションですが、リソースの需要の週ごとの変化をグラフ化するには便利です)。

私が持っているのは、私が制御できないレガシーのアーカイブ/レコード管理システムからの毎週のデータ抽出(パイプ区切りのフラットファイル)だけです。

各行は基本的にこれに蒸留することができます:
resource_id | resource info | customer_id | customer_info

サンプルデータ:

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

目標は、(最後のヒットに基づいて)Xか月間使用されていないリソースについて簡単にレポートできるようにすることです。リソースが人気がある場合、アクセスを容易にするためにリソースが保持される保持期間があります。 18か月間使用されていないリソースは、他の場所で長期アーカイブの対象としてマークされています。

これはよくある問題です。データセット間で何が新しい/同じ/削除されたかを判断するための汎用アルゴリズムがあるかどうか(dbと最新の抽出)

9
Swartz

さてあなたの答えは...はい。他に必要なものを必要としない、実装可能な単純なアルゴリズムがあります。これは正味現在価値アルゴリズムです。実装は簡単であり、DB側で必要なことは、週ごとのデータに日付スタンプを付けて、1つの単純なクエリと1つの小さな再帰関数またはforループを作成することです。または、これらの他のソリューションのいずれかを実行できます。

NPV = PV-(PV(CP/T)または新しい現在価値は、現在価値に現在の期間(最後のエントリからの月数)を掛けたもの(期間(例:18か月))で割って、リソース値が0になると、正味現在価値になります。費やされています。

あなたが私に欲しい言語を私に与えたら、私は編集でここにコードを投稿します

1
J-Boss

元の投稿から、取り込んだデータにはトランザクションの日時を示すフィールドがないようですが、ファイルは毎日、毎時などのスケジュールで頻繁に取り込まれていると思います。

これを処理するには、データベースレベルで自動生成されるSQLタイムスタンプ列を追加するか、データを抽出してDBに挿入するコードを使用します。次に、そのタイムスタンプ列にインデックスを配置し、それで完了です。 DBエンジンに、「今回から発生していないトランザクションの数」または「今回からその時間までの間に発生したトランザクションの数」という質問に効率的に答える仕事をさせましょう。

次に、レポートする差分をクエリして計算するジョブをスケジュールします。 「新規」のトランザクションとは、「新規」から要求する日付の前に、DBにレコードがないトランザクションです。古いレコードとは、締切日以降にトランザクションがないレコードです。

0
Thomas Carlisle

代替案:

  1. トランザクションのリストを配列などのある種のデータ構造に解析します。 (C++ではVector、JavaではArrayListと考えてください。)

  2. SELECT DISTINCT customer_id FROM Transactions ORDER BY customer_idなどのSQLバックエンドでクエリを実行し、並べ替えられた個別の顧客IDをセットoldにパックします。古いトランザクションと新しいトランザクションをWHERE句で区切ってまったく同じことを行う場合は、手順3をスキップできます。

  3. 新しい更新から一意の顧客IDを、ソートされた順序で別のデータ構造に取得します。データ構造newを取得するために使用できるデータ構造がいくつかあります。ダブルリンクリストへの挿入ソートは非常に単純ですが、中間ハッシュテーブルを使用すると、ほぼ線形の時間で実行されます。または、とにかく元の配列をソートしている場合は、そのセットを簡単に取得できます。

  4. お好みの言語の標準ライブラリを使用して、セットの違いnew-oldを取得します。あなたの好きな言語の標準ライブラリにはこのアルゴリズムがありますか?

トランザクションデータベースを更新した後、他に行うことは間違いなくSQLクエリです。

ステップ3に関する注意:データの性質を考慮してください。テキストファイルに注文が時系列でリストされているとします。通常の週に、新しいcustomer_idが昇順で与えられる多くの初めての顧客がいます。他のほとんどの注文が、少数の忠実なリピート顧客からであり、customer_idが低いと仮定します。次に、入力はすでにほとんどソートされています。ダブルリンクリストの前に低いcustomer_idを挿入し、後ろに高いcustomer_idを挿入しようとする挿入ソートは、その状況では実際にうまく機能します。

0
Davislor

あなたの質問からわかるように、実際にはresource_id(+ info)とcustomer(id + info)の「リスト」があります。

したがって、リソースごとの顧客のリストを簡単に保持し、リソースの各リストの最後のノードを確認できます(最後の操作時間を知るために、コードで顧客に日付フィールドを追加するだけです)

私はSQLに慣れていないので、HashMapとListを使用した例を示しますが、同じ考えだと思います:HashMap <Resource, List<Customer>>ResourceにはリソースIDをキーとして含める必要があり、Customerにはお客様ID、情報、操作日を含める必要があります。

このアイデアを使用すると、前回の操作時間を簡単に把握し、任意のリソースを変更できます(リソースの追加\削除\顧客)。

0
AsfK

SqLiteデータベースを使用している場合、バッチの日付をテーブルの列としても追加すると、

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

sQLを使用して、過去X日間使用されなかったリソースを取得するのはかなり簡単です。

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

私はSQLをテストしていませんが、それはあなたにアイデアを与えるはずです

0

とにかくSQLiteバックエンドで更新を保持している場合は、毎週の更新を新しいテーブルに変換し、それをマージする前にクエリでアーカイブデータと比較できます。

SQLを使用してテーブルへの新しい追加を見つける例: https://stackoverflow.com/questions/2077807/sql-query-to-return-differences-between-two-tables

DBのフィールドにトランザクションの日付が格納されている場合、過去18か月間にトランザクションがあったすべてのユーザーにクエリを実行できます。その場合、アーカイブは完全なDBです。または、まだアクセスしていないすべてのユーザーにクエリを実行し、データを抽出してから削除することもできます。更新は、今週にタイムスタンプが付けられた任意の行です。

0
Davislor