【问题标题】:Linq to SQL - Query with multiple joins, sum, grouping, havingLinq to SQL - 使用多个连接、求和、分组进行查询
【发布时间】:2017-10-31 13:42:25
【问题描述】:

我想将以下查询翻译成 linq。

SELECT
SUM(Credits.CreditAmount)
,Transactions.Id
,Person.FullName
,Person.Id
FROM
Person
JOIN
Transactions
ON Person.AccountId = Transactions.AccountId
JOIN Credits
ON Transactions.Id = Credits.TransactionId
WHERE
Person.Type = 'AccountHolder'
AND Person.Status = 'Active'
AND Transactions.CancelledDate IS NULL
AND Credits.CancelledDate IS NULL
GROUP BY Transactions.AccountId, Person.FullName, Person.Id
HAVING SUM(Credits.CreditAmount) > 20

这就是我想出的。这绝对是一头猪……它生成的SQL一定很糟糕。

var query = from p in Person
            join t in Transactions
            on p.AccountId equalas t.AccountId
            join c in Credits
            on t.TransactionId = c.TransactionId
            where p.Status == "Active" &&
            p.Type = "AccountHolder" &&
            t.CancelledDate == null &&
            c.CancelledDate == null
            group new { c.CreditAmount, t.AccountId, p.FullName, p.Id } by new { t.AccountId, p.FullName, p.SSN } into grp
            let sumC = grp.Select(x => x.CreditAmount).Sum()
            select new
            {
                TotalCredit = sumC,
                AccountId = grp.Key.AccountId,
                FullName = grp.Key.FullName,
                Id = grp.Key.Id
            };
query.Where(p => p.TotalServiceCredit > 20);

SQL 查询运行大约需要 3 秒,但我还没有耐心让 Linq 查询完成。我想知道我是否应该做一些不同的事情来完成我正在尝试编写的这个“组,总和,拥有”查询?我可以做些什么来帮助 Linq 生成更高性能的 SQL?

更新

事实证明 sgmoore 的想法是正确的。性能问题的关键在于他的回答。

这之间的区别

let sumC = grp.Select(x => x.CreditAmount).Sum()

还有这个

TotalCredit = grp.Sum(x => x.CreditAmount)

是完成的查询和没有完成的查询之间的区别。

请参阅下面我修改后的 LINQ 查询,该查询的完成时间与 SQL 差不多(SQL 为 5.3 秒,LINQ 为 5.6 秒)。

var query = from p in Person
        join t in Transactions
        on p.AccountId equalas t.AccountId
        join c in Credits
        on t.TransactionId = c.TransactionId
        where p.Status == "Active" &&
        p.Type = "AccountHolder" &&
        t.CancelledDate == null &&
        c.CancelledDate == null
        group new { c.CreditAmount, t.AccountId, p.FullName, p.Id } by new { t.AccountId, p.FullName, p.SSN } into grp
        select new
        {
            TotalCredit = grp.Sum(x => x.CreditAmount),
            AccountId = grp.Key.AccountId,
            FullName = grp.Key.FullName,
            Id = grp.Key.Id
        };
query.Where(p => p.TotalServiceCredit > 20);

感谢您的帮助!

【问题讨论】:

  • 您为什么要尝试将 SQL 查询转换为 LINQ?如果 SQL 执行得很快,为什么要打扰一件好事呢?
  • 我将其用作学习练习,以加深我对 LINQ 的理解。您的建议当然是实用的解决方案,但是“不要使用 LINQ”并不能帮助我了解 LINQ。这是一个相对简单的聚合查询。我只是对如何使用 LINQ 完成此任务感兴趣。
  • 非常好。你从两者中得到相同的结果吗?或者由于性能问题,您永远不会让它从 LINQ 返回行。
  • 我从不让它完成。我放的最长的是一分钟。 SQL 5 秒后返回。

标签: sql linq linq-to-sql


【解决方案1】:

我不同意 WEI_DBA 的评论,但是如果您需要这样做,那么您可能会发现将其分成几个查询更容易,例如

    var query1 = from p in Person
        join t in Transactions on p.AccountId equals t.AccountId
        join c in Credits  on t.TransactionId equals c.TransactionId

        where p.Status == "Active" &&
        p.Type = "AccountHolder" &&
        t.CancelledDate == null &&
        c.CancelledDate == null
        select new { c.CreditAmount, t.AccountID, p.FullName, p.Id};


    var query2 = (from p in query1
        group p by new { p.AccountId, p.FullName, p.Id } into grp

        select new
        {
            TotalCredit = grp.Sum(x => x.CreditAmount),
            AccountId   = grp.Key.AccountId,
            FullName    = grp.Key.FullName,
            Id          = grp.Key.Id
        };


    var query3 = (from p in query2 where p.TotalCredit > 20 select p); 

然后你可以让 LINQ 把它组合成一个 sql 命令。

与往常一样,检查和验证生成的实际 TSQL 是个好主意。

【讨论】:

  • 谢谢,我去看看!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-24
  • 1970-01-01
  • 1970-01-01
  • 2012-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多