2

我有以下类型的数据:

   会计日期从到Amt
1) 今天 ABC 100 美元
2) 今日ABC CAD USD -250
3) 今日 DEF 英镑 300 澳元
4) 今日 DEF 200 英镑


我需要对数据进行分组并对金额求和。为此,我需要对相反的货币进行净值计算,结果应该是:

   会计日期从到Amt
1) 今日ABC CAD USD -150
2) 今日 DEF 500 英镑


我正在使用.Net 3.5。我只能从货币中获取相同的数据:

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

编辑到最后以获取对第二个代码块的解释和一个以粗体显示的重要免责声明。

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. 选择总数(这样我们只需执行一次)。为此,请添加所有定向数量。

  4. 如果总值是正数(我这样做的方式),我们有一个净值进入最大的按字典顺序排列的货币名称。如果它是负数,则净值将进入按字典顺序排列的最小货币名称。

但是,我不相信这些是好的要求(或者我误解了最初的要求)。如果你看这个问题是解决什么问题,它将“AB 卖出”、“AB 买入”、“BA 买入”和“BA 卖出”组合为一组。在这种情况下,“AB 100”表示“AB -100”。第一个意味着买 100 个 A。第二个意味着把 100 个 B 卖给 A。如果你看一下这个问题的解决方式, 它们是一回事。 但实际上, 它们不是一回事。 卖 100 B 不会给你和买 100 A 一样多的 A。您需要汇率来使其正常化。

于 2013-10-19T07:01:50.277 回答