如何在linq中进行聚合查询

时间:2011-04-06 05:15:24

标签: linq sum aggregate

我是linq的新手,我需要帮助。我有一个带有金额字段的交易表,我希望将金额字段拆分为借方和贷方。与以下sql查询等效的linq是什么: 选择金额(金额< 0?金额:0)作为借方,金额(金额> 0?0:金额)作为来自Account = strAccount的交易的贷方。

3 个答案:

答案 0 :(得分:10)

不幸的是,没有简单方法在单个LINQ查询中表达聚合,就像它在获取单个结果时一样。两个单独的查询将是:

// Doesn't actually perform a query yet
var accountTransactions = db.Transactions.Where(t => t.AccountId == accountId);

var credit = accountTransactions.Sum(t => t.Amount > 0 ? t.Amount : 0);
var debit = accountTransactions.Sum(t => t.Amount < 0 ? t.Amount : 0);

或者:

var credit = accountTransactions.Sum(t => Math.Max(t.Amount, 0));
var debit = accountTransactions.Sum(t => Math.Min(t.Amount, 0));

我无法保证这些内容会在(例如)LINQ to SQL中有翻译,但我希望他们会这样做。

如果您找到所有帐户的信用卡/借记卡,可以在单个查询中执行此操作:

var query = from account in db.Accounts
            join transaction in db.Transactions
              on account.AccountID equals transaction.TransactionID
              into trans
            select new { Account = account,
                         Credit = trans.Sum(t => Math.Max(t.Amount, 0)),
                         Debit = trans.Sum(t => Math.Min(t.Amount, 0)) };

现在你可以使用:

var myTransactions = query.Where(result => result.Account.AccountId == accountID)
                          .FirstOrDefault();

然后成为单个SQL语句,返回单个结果,如果找不到该帐户ID,则返回null。同样,您必须看到实际如何将其转换为SQL。

答案 1 :(得分:1)

您可以发表如下声明:

var query = from t in db.Transactions
            where t.Account == strAccount
            group t by t.Account into grouping
            select new
            {
                Debit = grouping.Sum(x => x.Amount < 0 ? x.Amount),
                Credit = grouping.Sum(x => x.Amount > 0 ? x.Amount),
            };

这将SQL转换为:

SELECT SUM(
    (CASE 
        WHEN [t0].[Amount] < @p1 THEN [t0].[Amount]
        ELSE @p2
     END)) AS [Debit], SUM(
    (CASE 
        WHEN [t0].[Amount] > @p3 THEN [t0].[Amount]
        ELSE @p4
     END)) AS [Credit]
FROM [Accounts] AS [t0]
WHERE [t0].[Account] = @p0
GROUP BY [t0].[Account]

与原始版本不完全相同 - 您需要运行查询分析器才能了解GROUP BY对数据库的影响是否显着。

答案 2 :(得分:0)

db.Transactions
    .Select(t => new { CR=Math.Min(0,t.Amount), DB=Math.Max(0,t.Amount) })
    .Aggregate(new { CR=0, DB=0 }, (s, t) => return new { CR=s.CR+t.CR, DB=s.DB+t.DB });

这样做的好处是只在事务表上运行一次。但是,这会创建大量临时对象,每个事务对应一个。

如果您需要节省内存使用量,请对事务执行两次单独的传递:

var cr = db.Transactions.Sum(t => Math.Min(0,t.Amount));
var db = db.Transactions.Sum(t => Math.Max(0,t.Amount));