如何在LINQ中执行聚合查询

31moq8wy  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(125)

我有一个包含金额字段的交易表,我想将金额字段拆分为Debit和Credit。下面的SQL查询的LINQ等价形式是什么?

Select sum(Amount < 0 ? Amount : 0) as Debit, sum(Amount > 0 ? 0 : Amount) as Credit
from transactions
where Account = strAccount
pftdvrlh

pftdvrlh1#

不幸的是,在获取单个结果时,没有一种 * 简单 * 的方法可以在单个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到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,则返回空值。同样,您必须看到它实际上是如何转换为SQL的。

yzuktlbb

yzuktlbb2#

您可以使用如下语句:

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对数据库的影响是否显著。

jw5wzhpr

jw5wzhpr3#

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));

相关问题