通过count()确实离开了join和group的Linq查询

时间:2013-03-06 14:56:52

标签: c# linq

如果我有一个具有多个条件且一个用户选择多个条件的规则,如何编写一个linq查询,为我提供所有规则,其中该规则中的每个条件都存在于用户的选定条件下?

以下是我目前在SQL中的做法:

表格

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查询相同。你会怎么做?

3 个答案:

答案 0 :(得分:1)

我在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

以下是逐行说明:

  1. ruleCriteria
  2. 获取规则
  3. { criteriaId, categoryId }ruleId之类的条件进行分组,并将其保存在rules
  4. 对于每个完整规则,请检查匹配userCriteria的数量是否与规则总数相同,这意味着用户具有所有条件。
  5. 只选择此论坛的密钥,即ruleId

答案 1 :(得分:1)

此查询生成的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以检查事物是否为空。

答案 2 :(得分:0)

除非我误解(因此过于简单地解决问题),否则所有.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));

这将只返回所有包含标准符合您条件的rulls。我不能保证你的sql