0

RavenDB で groupby クエリが評価されるのはいつですか? での以前の質問の続きです。理論的にクエリしやすい形式にデータを完全に再構築することにしました。

新しいデータ構造を作成したので、それを照会する方法を見つけるのに苦労しています。

次の SQL クエリを作成するのに 30 秒かかりました。これにより、まさに必要な結果が得られます。

    SELECT        GroupCompanyId, AccountCurrency, AccountName, DATEPART(year, Date) AS Year,
                                 (SELECT        SUM(Debit) AS Expr1
                                   FROM            Transactions AS T2
                                   WHERE        (T1.GroupCompanyId = GroupCompanyId) AND (T1.AccountCurrency = AccountCurrency) AND (T1.AccountName = AccountName) AND (DATEPART(year, 
                                                             Date) < DATEPART(year, T1.Date))) AS OpeningDebits,
                                 (SELECT        SUM(Credit) AS Expr1
                                   FROM            Transactions AS T2
                                   WHERE        (T1.GroupCompanyId = GroupCompanyId) AND (T1.AccountCurrency = AccountCurrency) AND (T1.AccountName = AccountName) AND (DATEPART(year, 
                                                             Date) < DATEPART(year, T1.Date))) AS OpeningCredits, SUM(Debit) AS Db, SUM(Credit) AS Cr
    FROM            Transactions AS T1
    WHERE        (DATEPART(year, Date) = 2011)
    GROUP BY GroupCompanyId, AccountCurrency, AccountName, DATEPART(year, Date)
    ORDER BY GroupCompanyId, AccountCurrency, Year, AccountName

これまでのところ、次のように Map/Reduce を取得しました。Studio からは正しい結果が得られるようです。つまり、データを日付別に分類してグループ化します。

public Transactions_ByDailyBalance()
    {
        Map = transactions => from transaction in transactions
                              select new
                                     {
                                         transaction.GroupCompanyId,
                                         transaction.AccountCurrency,
                                         transaction.Account.Category,
                                         transaction.Account.GroupType,
                                         transaction.AccountId,
                                         transaction.AccountName,
                                         transaction.Date,
                                         transaction.Debit,
                                         transaction.Credit,
                                     };
        Reduce = results => from result in results
                            group result by new
                                            {
                                                result.GroupCompanyId,
                                                result.AccountCurrency,
                                                result.Category,
                                                result.GroupType,
                                                result.AccountId,
                                                result.AccountName,
                                                result.Date,
                                            }
                            into g
                            select new
                                   {
                                       GroupCompanyId = g.Select(x=>x.GroupCompanyId).FirstOrDefault(),
                                       AccountCurrency = g.Select(x=>x.AccountCurrency).FirstOrDefault(),
                                       Category=g.Select(x=>x.Category).FirstOrDefault(),
                                       GroupType=g.Select(x=>x.GroupType).FirstOrDefault(),
                                       AccountId = g.Select(x=>x.AccountId).FirstOrDefault(),
                                       AccountName=g.Select(x=>x.AccountName).FirstOrDefault(),                                           
                                       Date=g.Select(x=>x.Date).FirstOrDefault(),
                                       Debit=g.Sum(x=>x.Debit),
                                       Credit=g.Sum(x=>x.Credit)
                                   };

        Index(x=>x.GroupCompanyId,FieldIndexing.Analyzed);
        Index(x=>x.AccountCurrency,FieldIndexing.Analyzed);
        Index(x=>x.Category,FieldIndexing.Analyzed);
        Index(x=>x.AccountId,FieldIndexing.Analyzed);
        Index(x=>x.AccountName,FieldIndexing.Analyzed);
        Index(x=>x.Date,FieldIndexing.Analyzed);
    }
}       

ただし、データを一度にクエリする方法がわかりません。期首残高と期間残高が必要なので、アカウントをパラメーターとして受け取るこのクエリを作成することになりました。以前の質問に対する Oren のコメントに続いて、Linq と Lucene クエリを混合し、クエリを書き直して、基本的に混合クエリで再び終了しました。

上記の SQL クエリでは、年ごとにフィルター処理していることを示していますが、実際には、現在の残高を任意の日から判断できる必要があります。

     private LedgerBalanceDto GetAccountBalance(BaseAccountCode account, DateTime periodFrom, DateTime periodTo, string queryName)
    {
        using (var session = MvcApplication.RavenSession)
        {
            var query = session.Query<Transactions_ByDailyBalance.Result, Transactions_ByDailyBalance>()
                .Where(c=>c.AccountId==account.Id && c.Date>=periodFrom && c.Date<=periodTo)
                .OrderBy(c=>c.Date)
                .ToList();

            var debits = query.Sum(c => c.Debit);
            var credits = query.Sum(c => c.Credit);

            var ledgerBalanceDto = new LedgerBalanceDto
                                   {
                                       Account = account,
                                       Credits = credits,
                                       Debits = debits,
                                       Currency = account.Currency,
                                       CurrencySymbol = account.CurrencySymbol,
                                       Name = queryName,
                                       PeriodFrom = periodFrom,
                                       PeriodTo = periodTo
                                   };

            return ledgerBalanceDto;
        }
    }

必要な結果:

    GroupCompanyId  AccountCurrency AccountName Year    OpeningDebits   OpeningCredits  Db  Cr
    Groupcompanies-2    EUR Customer 1  2011    148584.2393 125869.91   10297.6891  28023.98
    Groupcompanies-2    EUR Customer 2  2011    236818.0054 233671.55   50959.85    54323.38
    Groupcompanies-2    USD Customer 3  2011    69426.11761 23516.3776  10626.75    0
    Groupcompanies-2    USD Customer 4  2011    530587.9223 474960.51   97463.544   131497.16
    Groupcompanies-2    USD Customer 5  2011    29542.391   28850.19    4023.688    4231.388

どんな提案でも大歓迎です

ジェレミー

コメントへのお返事で

私は基本的にほとんど同じことをしました。実際、私は 2 回のヒットでそれを実行するインデックスを作成しました。これは、アカウント名、カテゴリなどでグループ化する場合、ほぼ瞬時です。

ただし、私の問題は、個々のアカウントの毎日の実行残高を取得することです。アカウントと期間のすべてのデータを取得しても問題ありません。ただし、データがページングされ、借方と貸方が日付と ID によってグループ化されている場合、クライアントの残高を合計できます。ページング日付をまたぐので、始末バランスが正しくありません。

Page 1

Opening balance until 26/7/12 = 0

25/7/12    Acct1       Db 100       Cr 0     Bal  +100    Runn Bal +100
26/7/12    Acct1       Db 100       Cr 0     Bal  +100    Runn Bal +200
26/7/12    Acct1       Db 200       Cr 0     Bal  +200    Runn Bal +400

Closing balance until 26/7/12 = +400

Page 2
Opening balance until 26/7/12 = +450 (this is wrong - it should be the balance at the end of Page 1, but it is the balance until the 26/7/12 - i.e. includes the first item on Page 2)
26/7/12    Acct1       Db 50        Cr 0     Bal  +50     Runn Bal +500 (should be +450)
27/7/12    Acct1       Db 60        Cr 0     Bal  +60     Runn Bal +560 (should be +510)

これを処理するアルゴリズムを考え出すことはできません。

何か案は?

4

1 に答える 1

1

こんにちは、これは私が最近RavenDbで直面した問題であり、考えられるあらゆる日付でローリングバランスを取得する必要がありました。これを一度に行う方法は見つかりませんでしたが、ローリングバランスを計算するためにプルバックする必要のあるドキュメントの量を減らすことができました。

これは、特定の期間内のトランザクションの値を合計する複数のマップリデュースインデックスを作成することで実現しました。

  1. 私の最初の年レベルでグループ化されたすべてのトランザクションの値を合計しました
  2. 私の2番目のインデックス日レベルでのすべてのトランザクションの値を合計しました

したがって、誰かがアカウントの残高を希望する場合は、2012年6月1日時点で次のようになります。

  1. 年レベルのMap-reduceインデックスを使用して、2012年までのトランザクションの値を取得し、それらを合計します(したがって、トランザクションが2009年にキャプチャされ始めた場合は、3つのドキュメントをプルバックする必要があります)
  2. 日レベルのMap-reduceインデックスを使用して、年の初めから6月1日までのすべてのドキュメントを取得します

次に、最終的なローリングバランスの年の合計に日数の合計を追加しました(月次マップも減らすこともできましたが、気にしませんでした)。

とにかくSQLほど速くはありませんが、すべてのトランザクションを戻さないようにするために私が思いついた最良の選択肢でした

于 2012-08-22T08:08:29.977 に答える