2

次のタイプのデータがあります。

   会計日 自 至 金額
1) ABC 今日 USD CAD 100
2) ABC 今日の CAD USD -250
3) 今日の DEF GBP AUD 300
4) 今日の DEF GBP AUD 200


データをグループ化し、金額を合計する必要があります。そのためには、結果が次のようになるように、反対の通貨を相殺する必要があります。

   会計日 自 至 金額
1) ABC 今日の CAD USD -150
2) 今日のDEF GBP AUD 500


私は.Net 3.5を使用しています。from と to の通貨が同じデータのみをネッティングできました。

var net = data.GroupBy(x=> new { x.Acct, x.Date, x.From, x.To})
.Select new {y.Key.Acct, y.Key.Date, y.Key.From, y.Key.To, Net = y.Sum(x => x.Amt)});

類似通貨と反対通貨の両方をネッティングする方法はありますか?

4

1 に答える 1

0

EDITコードの 2 番目のブロックの説明と太字の重要な免責事項については、最後に移動してください。

var query = from acct in accts
    select new
    {
        acct.From,
        acct.To,
        acct.Amount,
        FirstOrientedAmount = ((acct.From.CompareTo(acct.To) == -1 && acct.Amount < 0) ||
            (acct.From.CompareTo(acct.To) >= 0 && acct.Amount > 0)) ? acct.Amount : 0,
        SecondOrientedAmount = ((acct.From.CompareTo(acct.To) >= 0 && acct.Amount < 0) ||
            (acct.From.CompareTo(acct.To) == -1 && acct.Amount > 0)) ? acct.Amount * -1 : 0
    } into r
    group r by new
    {
        First = (r.From.CompareTo(r.To) == -1 ? r.From : r.To),
        Second = (r.From.CompareTo(r.To) == -1 ? r.To : r.From)
    } into g
    select new
    {
        First = g.Sum(acctval => acctval.FirstOrientedAmount) + g.Sum(acctval => acctval.SecondOrientedAmount) > 0 ? g.Key.Second : g.Key.First,
        Second = g.Sum(acctval => acctval.FirstOrientedAmount) + g.Sum(acctval => acctval.SecondOrientedAmount) > 0 ? g.Key.First : g.Key.Second,
        FTotal = g.Sum(acctval => acctval.FirstOrientedAmount),
        STotal = g.Sum(acctval => acctval.SecondOrientedAmount),
        Total = g.Sum(acctval => acctval.FirstOrientedAmount) + g.Sum(acctval => acctval.SecondOrientedAmount),
    };

これは与える:

CAD USD -150
GBP AUD 500

編集:これらの要件を完全には理解していないため、古いコードを残していますが、最適化するためにコンパイラに依存しないものを投稿しています:

var query = from p in accts
    select new
    {
        p.From,
        p.To,
        p.Amount,
        OrientedAmount = ((p.From.CompareTo(p.To) == -1 && p.Amount < 0) ||
            (p.From.CompareTo(p.To) >= 0 && p.Amount > 0)) ? p.Amount : p.Amount * -1
    } into r
    group r by new
    {
        First = (r.From.CompareTo(r.To) == -1 ? r.From : r.To),
        Second = (r.From.CompareTo(r.To) == -1 ? r.To : r.From)
    } into g
    select new
    {
        g.Key.First,
        g.Key.Second,
        Total = g.Sum(val => val.OrientedAmount)
    } into last
    select new
    {
        First  = last.Total > 0 ? last.Second : last.First,
        Second = last.Total > 0 ? last.First : last.Second,
        Total = last.Total
    };
  1. これは、最初にすべての金額を From アカウントが辞書式に並べられた最大の通貨名であるトランザクションに向けることによって機能します。現在のトランザクション ラインが辞書順で最小の通貨名に向かって資金を移動している場合は、金額の符号を反転させます。

  2. 次に、トランザクション内のアカウントを辞書順に並べてグループ化します。

  3. 合計を選択します (これを行う必要があるのは 1 回だけです)。これを行うには、すべての指向量を追加します。

  4. 合計値が正の場合 (私が行った方法)、辞書式に並べられた最大の通貨名に正味の値が入ります。負の場合、正味の値は辞書式に並べられた最小の通貨名になります。

ただし、これらが適切な要件であるとは確信していません (または、元の要件を誤解しています)。この問題が何を解決しているのかを見ると、「AB売り」「AB買い」「BA買い」「BA売り」を1つのグループにまとめています。この場合、「AB 100」は「AB -100」を意味します。1 つ目は 100 A を購入することを意味し、2 つ目は 100 B を A に売却することを意味します。この問題の解決方法を見ると、 それらは同じことです。 しかし実際には、 それらは同じものではありません。 100 B を売っても、100 A を買ったのと同じ量の A は得られません。これを正規化するには、為替レートが必要です。

于 2013-10-19T07:01:50.277 に答える