这里是一个示例数据集:
OrderProduct
是一个表,其中包含属于给定订单的产品 ID。
注意:OrderProduct 是一个数据库表,我使用的是 EF。
订单ID、产品ID
1, 1
2, 2
3, 4
3, 5
4、5
4, 2
5, 2
5, 3
我想要做的是找到一个仅包含我正在搜索的productId 的订单。因此,如果我的输入是productIds 2,3,那么我应该返回OrderId 5。
我知道如何对数据进行分组,但我不确定如何对组执行选择。
这是我所拥有的:
var q = from op in OrderProduct
group op by op.OrderId into orderGroup
select orderGroup;
不确定如何从这里继续
最佳答案
IEnumerable<int> products = new List<int> {2, 3};
IEnumerable<OrderProduct> orderProducts = new List<OrderProduct>
{
new OrderProduct(1, 1),
new OrderProduct(2, 2),
new OrderProduct(3, 4),
new OrderProduct(3, 5),
new OrderProduct(4, 5),
new OrderProduct(4, 2),
new OrderProduct(5, 2),
new OrderProduct(5, 3),
};
var orders =
(from op in orderProducts
group op by op.OrderId into orderGroup
//magic goes there
where !products.Except(orderGroup.Select(x => x.ProductId)).Any()
select orderGroup);
//outputs 5
orders.Select(x => x.Key).ToList().ForEach(Console.WriteLine);
或者您可以使用另一个答案中指出的另一个版本,只需替换
where !products.Except(orderGroup.Select(x => x.ProductId)).Any()
开
where products.All(pid => orderGroup.Any(op => op.ProductId == pid))
第二个的性能将提高约 15%(我已经检查过)
编辑
根据最后的需求更改,您需要的订单不包含您正在搜索的所有productId,而是包含这些且仅包含这些productId,我编写了更新版本:
var orders =
(from op in orderProducts
group op by op.OrderId into orderGroup
//this line was added
where orderGroup.Count() == products.Count()
where !products.Except(orderGroup.Select(x => x.ProductId)).Any()
select orderGroup);
因此,您唯一需要的是添加一个前提条件,确保集合包含相同数量的元素,它将适用于两个之前的查询,作为奖励,我建议最重要的 where 条件的第三个版本:
where orderGroup.Select(x => x.ProductId).Intersect(products).Count() == orderGroup.Count()
关于linq - Entity Framework Linq - 如何获取包含所有数据的组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9221850/