将相关表中的分组总和放入linq查询列

时间:2018-10-29 21:34:34

标签: sql-server linq join left-join

我想查询一个表(Accounts),并作为查询的一部分从另一个表(AccountPositions)中获取总数(Total)。如何将该SQL查询重写为linq查询?就像添加一个按语句分组一样容易...但是按用法分组使我感到困惑。

select 
(select sum(ap.Quantity * ap.LastPrice) from AccountPositions ap 
  where ap.AccountId = a.Accountid and ap.IsOpen = 0) as Total,
a.AccountId, a.Username, a.FirstName, a.LastName, a.AccountNumber
from Accounts a
where a.IsTrading = 1

类似的东西

var query = (from a in _context.Accounts
            join ap in _context.AccountPositions on ap.AccountId = a.AccountId
            where a.IsTrading == true && and ap.IsOpen == true
            select new {
                Total = ap.Sum(r => r.Quantity * r.LastPrice),
                AccountId = a.AccountId,
                Username = a.Username,
                FirstName = a.FirstName,
                LastName = a.LastName,
                AccountNumber = a.AccountNumber
                }); 

所需结果:

Total   AccountId   Username    FirstName   LastName    AccountNumber
2500    496         brice       Brian       Rice        U399445
160     508         jdoe        John        Doe         U555322                                                             

表格:

Accounts
AccountId   Username    FirstName   LastName    AccountNumber   IsTrading
496         brice       Brian       Rice        U399445         1
498         bmarley     Bob         Marley      U443992         0
508         jdoe        John        Doe         U555332         1

AccountPositions
AccountPositionId   AccountId   Quantity    LastPrice   IsOpen
23                  496         10          200         1
24                  496         15          48          0
25                  508         8           20          1
26                  498         18          35          1
27                  496         5           100         1

1 个答案:

答案 0 :(得分:2)

  

如何将该SQL查询重写为linq查询?是否像通过语句添加组一样容易...

这甚至更容易,因为所讨论的SQL查询在select子句中使用单个聚合返回相关子查询,因此对LINQ的转换实际上是一对一的-只需使用相应的C#运算符,并记住在LINQ {{ 1}}走到最后。像select这样的聚合方法在LINQ 查询语法之外:

Sum

但是LINQ允许您将查询语法方法语法混合使用,因此var query = from a in _context.Accounts where a.IsTrading select new { Total = (from ap in _context.AccountPositions where ap.AccountId == a.AccountId && ap.IsOpen select ap.Quantity * ap.LastPrice).Sum(), a.AccountId, a.Username, a.FirstName, a.LastName, a.AccountNumber }; 部分可以使用下面这样的形式更自然地编写:

Sum

最后,如果您使用的是Entity Framework,则Total = _context.AccountPositions .Where(ap => ap.AccountId == a.AccountId && ap.IsOpen) .Sum(ap => ap.Quantity * ap.LastPrice), Account之间的关系将由类似的

表示
AccountPosition
public ICollection<AccountPosition> AccountPositions { get; set; } 类中的

导航属性。这样就可以忽略诸如Account之类的联接(相关)条件-它们将自动应用,并且仅关注查询逻辑(请参见Don’t use Linq’s Join. Navigate!),例如

ap.AccountId == a.AccountId

在LINQ查询中,EF集合导航属性表示所谓的grouped join-独特的LINQ功能(至少在SQL中没有直接等效的功能)。在LINQ查询语法中,它表示为Total = a.AccountPositions.Where(ap => ap.IsOpen).Sum(ap => ap.Quantity * ap.LastPrice), + join子句。假设您需要多个集合。分组联接将帮助您实现不重复相关部分的功能。

因此,对于您的模型,使用分组联接的查询将像这样开始:

into

从这里开始,您有2个变量-from a in _context.Accounts join ap in _context.AccountPositions on a.AccountId equals ap.AccountId into accountPositions 代表a,而Account代表与accountPositions相关的AccountPosition的集合。

但是您只对空缺职位感兴趣。为了避免重复该条件,可以使用另一个LINQ 查询语法构造-let子句。因此查询继续使用两个过滤器:

Account

现在,您拥有生成最终结果的所有信息,例如:

where a.IsTrading
let openPositions = accountPositions.Where(ap => ap.IsOpen)