3

多くの基準を持つルールがあり、ユーザーが複数の基準を選択した場合、そのルール内のすべての基準がユーザーの選択した基準とともに存在するすべてのルールを提供する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クエリと同じです。どうしますか?

4

3 に答える 3

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を生成して、nullかどうかを確認する必要があるためです。

于 2013-03-06T20:52:53.127 に答える
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. のように基準をグループ{ criteriaId, categoryId }化し、ruleIdに保存しますrules
  3. ルール全体について、一致するuserCriteria数がルールの総数と同じであるかどうか、つまりユーザーがすべての基準を持っているかどうかを確認します。
  4. このグループのキーだけを選択します。これはruleIdです。
于 2013-03-06T16:12:50.280 に答える
0

私が誤解していない限り(したがって、問題を単純化しすぎていない限り)、おそらく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を保証することはできません

于 2013-03-06T15:20:08.080 に答える