如何在 LINQ 中使用 SUM 和 GROUP BY 函数
How to use SUM and GROUP BY function in LINQ
实际上,我在 LINQ 中遇到了问题,请帮我解决这个问题。让我分享我的问题。我有 2 tables 和我在一起。
表 1
LocationID LoginID LocationName
1 101 A
2 101 B
3 101 C
在此 table 中,我们显示的是位置名称列表。
表 2
ID LoginID STOCKID QUANTITY LocationID
1 101 1 10 1
2 101 1 -8 1
3 101 2 20 2
4 101 2 -5 2
5 101 1 30 1
在此table中,我们显示了不同位置的库存商品数量列表。
现在,我想要的结果是分别显示每个位置的库存商品总量。
结果应该是这样的:
LocationID LocationName QUANTITY
1 A 32
2 B 15
让我与您分享我的代码。
public ActionResult GetStockQuantityPartial(int? Stock_ID)
{
string loginId = Convert.ToString(Session["LoginId"]);
var emp = (from m in context.StockMovements
join o in context.Locations
on m.Location equals o.LocationID
where m.Stock_ID == Stock_ID && m.LoginID == loginId
group new { m, o } by new { m.Location, m.Quantity, o.Location_Name } into grp
select new DisplayQuantityViewModel
{
Location = grp.Key.Location,
LocationName = grp.Key.Location_Name,
TotalStockQuantity = grp.Sum(x => x.m.Quantity)
}).ToList();
return PartialView("_DisplayStockQuantity", emp);
}
看起来问题是您在位置和数量上分组,而您只想在位置字段上对移动进行分组。
group m by new { o.LocationId, o.Location_Name } into grp
然后 SUM 行变为:
TotalStockQuantity = grp.Sum(x => x.Quantity)
据我了解,StockMovement 有一个 Location 字段,但这是 Location ID。借助 EF,将导航属性用于实体之间的 FK 关系是有益的。这样您就可以轻松地跨这些关系进行查询,并让 EF 计算出合适的 SQL。这可以导致更简单的表达式从对象图中读取而不是 SQL-like 连接。
例如,而不是这个:
public class StockMovement
{
// ... columns...
public int Location { get; set;}
}
...使用导航属性并解决 table..
中假定的列命名
public class StockMovement
{
// ... columns...
[ForeignKey("Location"), Column("Location")]
public int LocationId { get; set; }
public virtual Location Location { get; set; }
}
这假定 StockMovement table 中 LocationId 的列称为“位置”。使用 [Column]
属性或自定义映射(请参阅 EntityTypeConfiguration
以供参考)您可以配置 EF 以映射字段,这样您的 classes 可以保持一致的命名方法,即使 table他们没有提到。同样可以将 Location_Name 中的“Location_Name”更改为“LocationName”。您甚至可以通过利用 .Map(x => x.MapKey("Location"))
(EF6) 或影子属性来取消 FK 列 (LocationId)。 (EF 核心)
利用导航 属性 可以将表达式简化为:
var emp = context.StockMovements
.Where(x => x.Stock_ID == stockID && x.LoginID == loginId)
.GroupBy(x => new { x.Location.LocationId, x.Location.LocationName })
.Select(g => new DisplayQuantityViewModel
{
Location = g.Key.LocationId,
LocationName = g.Key.LocationName,
TotalStockQuantity = g.Sum(x => x.Quantity)
}).ToList();
从对象图/C# 的角度来看,我发现这比 Linq 语法更容易理解,所以把它扔在那里作为一个可供考虑的选项。
实际上,我在 LINQ 中遇到了问题,请帮我解决这个问题。让我分享我的问题。我有 2 tables 和我在一起。
表 1
LocationID LoginID LocationName
1 101 A
2 101 B
3 101 C
在此 table 中,我们显示的是位置名称列表。
表 2
ID LoginID STOCKID QUANTITY LocationID
1 101 1 10 1
2 101 1 -8 1
3 101 2 20 2
4 101 2 -5 2
5 101 1 30 1
在此table中,我们显示了不同位置的库存商品数量列表。
现在,我想要的结果是分别显示每个位置的库存商品总量。 结果应该是这样的:
LocationID LocationName QUANTITY
1 A 32
2 B 15
让我与您分享我的代码。
public ActionResult GetStockQuantityPartial(int? Stock_ID)
{
string loginId = Convert.ToString(Session["LoginId"]);
var emp = (from m in context.StockMovements
join o in context.Locations
on m.Location equals o.LocationID
where m.Stock_ID == Stock_ID && m.LoginID == loginId
group new { m, o } by new { m.Location, m.Quantity, o.Location_Name } into grp
select new DisplayQuantityViewModel
{
Location = grp.Key.Location,
LocationName = grp.Key.Location_Name,
TotalStockQuantity = grp.Sum(x => x.m.Quantity)
}).ToList();
return PartialView("_DisplayStockQuantity", emp);
}
看起来问题是您在位置和数量上分组,而您只想在位置字段上对移动进行分组。
group m by new { o.LocationId, o.Location_Name } into grp
然后 SUM 行变为:
TotalStockQuantity = grp.Sum(x => x.Quantity)
据我了解,StockMovement 有一个 Location 字段,但这是 Location ID。借助 EF,将导航属性用于实体之间的 FK 关系是有益的。这样您就可以轻松地跨这些关系进行查询,并让 EF 计算出合适的 SQL。这可以导致更简单的表达式从对象图中读取而不是 SQL-like 连接。
例如,而不是这个:
public class StockMovement
{
// ... columns...
public int Location { get; set;}
}
...使用导航属性并解决 table..
中假定的列命名public class StockMovement
{
// ... columns...
[ForeignKey("Location"), Column("Location")]
public int LocationId { get; set; }
public virtual Location Location { get; set; }
}
这假定 StockMovement table 中 LocationId 的列称为“位置”。使用 [Column]
属性或自定义映射(请参阅 EntityTypeConfiguration
以供参考)您可以配置 EF 以映射字段,这样您的 classes 可以保持一致的命名方法,即使 table他们没有提到。同样可以将 Location_Name 中的“Location_Name”更改为“LocationName”。您甚至可以通过利用 .Map(x => x.MapKey("Location"))
(EF6) 或影子属性来取消 FK 列 (LocationId)。 (EF 核心)
利用导航 属性 可以将表达式简化为:
var emp = context.StockMovements
.Where(x => x.Stock_ID == stockID && x.LoginID == loginId)
.GroupBy(x => new { x.Location.LocationId, x.Location.LocationName })
.Select(g => new DisplayQuantityViewModel
{
Location = g.Key.LocationId,
LocationName = g.Key.LocationName,
TotalStockQuantity = g.Sum(x => x.Quantity)
}).ToList();
从对象图/C# 的角度来看,我发现这比 Linq 语法更容易理解,所以把它扔在那里作为一个可供考虑的选项。