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


9

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

  • 「新規」(または追加)- 抽出によって表示されていないため、アプリがこのリソースを以前に追跡していない可能性があるため、リソースはアプリにとって新しいものです。
  • 「更新」(またはヒット)-そのリソースが最近使用されており、保存期間がもう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と最新の抽出)

回答:


1

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

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

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


言語はそれほど重要ではありません。RubyまたはC ++を選択する必要がある場合。HTML 4.0 Strictでアルゴリズムを記述できる場合、あなたは私のヒーローになります。その最後の部分について冗談を言っている:)
Swartz

コードを見てみたいと思います。RubyまたはC ++。ありがとうございました。
Swartz

0

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

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

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


より良い、それは少なくともデータ中心のソリューションですが、それでもやり過ぎです
J-Boss

始めは簡単なので、当面はsqliteを使用しています。MySQL(またはPostgreSQL)に簡単に切り替えることができます。SQLを使用しないバックエンドを使用すると、この作業をさらに改善するために何でもネットに接続することができれば、私はすべての問題に耳を傾けます。
Swartz

まあ、私の考えは主に、とにかくそれをデータベースの行に変換することでした。複数のプロセスから同時に実行する必要がない場合は、SQLiteよりも重いものに切り替えたくないと思います。
Davislor

並行処理の必要はありません。しかし、リソースに関するデータをどこかに保存する必要があります。SQL dbは良い選択のように思われましたが、デルタを処理するためにデータを任意のデータ型にロードすることを妨げるものは何もありません。各抽出実行の最後に必要なのは、何が新しく、何が変わらず、何が消えたかを理解することです。この情報から、必要に応じてレコードを更新する方法を見つけることができます。
Swartz

データを解析してデータベースに入れたら、アルゴリズムを実装するよりもクエリを書く方がおそらく簡単です。とはいえ、コード化したい場合、必要なアルゴリズムは違いがあり、C ++ STLには、両方のデータセットをのコンテナーに入れたら、1行で実行するために使用できる実装があります。あなたの選択、おそらくVector
Davislor

0

代替案:

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

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

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

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

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

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


1
私は顧客よりも新しい/同じ/更新されたリソースに興味があります。しかし、はい、考え方は同じです。
Swartz

0

私はあなたの質問から理解できるように、実際にはresource_id(+ info)とcustomer(id + info)の「リスト」を持っています。

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

私は、SQLに精通していないよ、それゆえ私は私の例を与えるHashMapとリストが、私は確信して、それは同じ考えですよ:HashMap <Resource, List<Customer>>、ときResourceキーとしてRESOURCEIDが含まれている必要があり、Customer顧客ID、情報及び操作の日付が含まれている必要があります。

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


0

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

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

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

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


-2

これはHashTablesの目的ではありませんか?過去数か月間に使用されたリソースのレコードを保持し、過去18か月にアクセスされなかったリソースを削除するだけの場合は、キーがresource_idで値がHashTableであるHashTableを使用できます。最終アクセス日。

18か月を超えるレコードをアーカイブするには、ハッシュテーブル内のすべてのレコードを調べ、それらの特定のレコードを削除(または移動)するだけです。(レポートが届いたら、毎週行うことができます)


データをデータベースに格納しているのに、なぜHashTableが必要なのですか?dbレコードを更新できます。私はケースにもっと興味があります。2つのデータセットを取り、2つのセット間の違い(追加されたもの、同じまま、削除されたもの)を見つけます。HashTable技術は、新しい「削除された」レコードを見つけるのにどのように役立ちますか?
Swartz、2015

テーブルがデータベースでインデックス付けされている場合、それらは基本的にはHashTablesでもあります。2つのテーブルがあり、それぞれがデータセットを表している場合、いくつかの外部結合を行うことにより、新しいレコードと削除されたレコードを取得できます。これを参照してください:i.stack.imgur.com/pxUO3.png。resource_id列にインデックスがあることを確認します。これはかなり高速なはずです。これを最初から実装する必要がある場合は、H(1)の償却時間でルックアップ/挿入/削除を実行できるので、HashTablesを使用する方法がまだあると思います。これを行うためのより効率的な方法は考えられません。
エイドリアンBuzea

3
これをハッシュテーブルに詰め込む余分な手順なしでエージングを処理するより優れたデータ構造があります。

いくつか言及してもいいですか?
エイドリアンBuzea

@スノーマン-私はそれをもう数回評価できればいいのですが、このコメントで強く同意します
J-Boss
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.