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)
これを処理するアルゴリズムを考え出すことはできません。
何か案は?