Linq查询,通过count()进行左连接和分组
本文关键字:连接 查询 通过 count Linq | 更新日期: 2023-09-27 18:02:29
如果我有一个规则,其中有许多条件和用户选择多个条件,我如何编写一个linq查询给我所有的规则,其中每个条件在该规则中存在与用户选择的条件?
这是我目前在SQL中如何做的:
<<p> 表/strong>rule:
ruleId int
categoryId int
ruleCriteria:
ruleId int,
criteriaId int
@userCriteria:
criteriaId int
categoryId int
查询SELECT
r.ruleId
FROM dbo.rule r
INNER JOIN dbo.ruleCriteria rc ON r.ruleId= rc.ruleId
LEFT OUTER JOIN @userCriteria uc
ON rc.criteriaId = uc.criteriaId
AND r.categoryId = uc.categoryId
GROUP BY r.ruleId
HAVING COUNT(rc.criteriaId) = COUNT(uc.criteriaId)
对于linq查询,我将使用这些对象(更非规范化,但如果有帮助,我可以将它们放在与表相同的结构中):
userCriteria:
criteriaId int
categoryId int
ruleCriteria:
ruleId int
categoryId int
criteriaId int
我的目标与SQL查询相同,即获得匹配规则的不同列表。你会怎么做?
这个查询比另一个查询生成更好的SQL,而且它更直接:
from rc in ruleCriterias
group rc by rc.ruleId into rules
where rules.All(rc => userCriterias.Any(uc =>
uc.criteriaId == rc.criteriaId && uc.categoryId == rc.categoryId))
select rules.Key
您应该确保所有列都是NOT NULL
,因为如果它们不是,这必须生成额外的SQL来检查是否为空
我在LINQPad中玩了一些测试数据,这就是我想到的。
from rc in ruleCriteria
group new { rc.criteriaId, rc.categoryId } by rc.ruleId into rules
where rules.Count() == userCriteria.Count(uc =>
rules.Contains(new { uc.criteriaId, uc.categoryId }))
select rules.Key
下面是逐行解释:
- 从
ruleCriteria
获取规则 - 将
{ criteriaId, categoryId }
等标准按ruleId
分组保存在rules
- 对于每条完整的规则,检查匹配
userCriteria
的数量是否与规则的总数相同,这意味着用户拥有所有的条件。 - 只选择此组的密钥,即
ruleId
。
除非我误解了(因此过度简化了问题),否则您可能需要all . all()方法。
var userCriteria = ; //TODO: Build user criteria
var result = context.Rules.Where(r => r.CategoryId == userCriteria.CategoryId
&& r.RuleCriteria.All(rc => rc.id == userCriteria.CriteriaId));
这将只返回所有包含条件与您的条件匹配的规则。我不能保证你的sql