2011-07-26 10 views
1

私はEx_IdとTerm_Idの両方のint型の2つの列を持つテーブルを持っています。私のテーブルは、1つのエクササイズIDのタームIDがたくさんあります。この複数の条件に基づいてテーブルから値のリストを選択するクエリ

 Table would look like this: 
     Ex_Id Term_Id 
     1  2 
     1  3 
     1  4 
     1  5 
     2  2 
     3  2 
     3  4 

などEx_Idのリストを取得することが最も重要です。私の機能はこれのようになります。

List<int> Get_ExId_List(List<int> lst_TermId) 
{ 
    // return a list of Ex_Id <int> 
} 

つまり、私はTerm Idのリストを渡しますので、いくつかの基準に合ったExercise Idのリストを取得する必要があります。選択する基準は、改善することができ、この擬似コードで説明:私は上記のサンプルテーブルから、例えばのためにSELECT such Ex_Ids FROM table Exercise_Term WHERE Ex_Id has all the corresponding Term_Ids in the lst_TermId

List<int> Get_ExId_List([2]) 
{ 
    // return [1,2,3] 
} 

List<int> Get_ExId_List([2,4]) 
{ 
    // return [1,3] 
} 

List<int> Get_ExId_List([2,3,4]) 
{ 
    // return [1] 
} 

クエリ部分は私の混乱です。この条件でのクエリはどのようになりますか?休むことができます。希望の質問は明らかです。おかげで..

答えて

2
SELECT Ex_ID 
FROM TableName 
WHERE Term_ID IN (?, ?, ?)    --- (2, 3, 4) 
GROUP BY Ex_ID 
HAVING COUNT(DISTINCT Term_ID) = 3  --- number of terms in the above list 

組み合わせ(Ex_ID, Term_ID)は、テーブル内で一意である場合は、これは、リレーショナル分割問題であるCOUNT(*)

COUNT(DISTINCT Term_ID)を置き換えることができます。 "標準" ソリューションは、(NOT EXISTS)2枚のネガを使用することになります

SELECT DISTINCT Ex_ID 
FROM TableName e 
WHERE NOT EXISTS 
     (SELECT * 
      FROM TableName t 
      WHERE t.Term_ID IN (?, ?, ?)   --- the list of terms 
      AND NOT EXISTS 
        (SELECT * 
        FROM TableName a 
        WHERE a.Term_ID = t.Term_ID 
         AND a.Ex_ID = e.Ex_ID 
       ) 
     ) 

またはより良いあなたのケースで:

SELECT DISTINCT Ex_ID 
FROM TableName e 
WHERE NOT EXISTS 
     (SELECT * 
      FROM 
      (SELECT ? AS Term_ID 
      UNION 
       SELECT ? 
      UNION 
       SELECT ? 
      ) AS t 
      WHERE NOT EXISTS 
        (SELECT * 
        FROM TableName a 
        WHERE a.Term_ID = t.Term_ID 
         AND a.Ex_ID = e.Ex_ID 
       ) 
     ) 

+0

これを試してください。ありがとう。このクエリは確かに難しいです。 – nawfal

1

あなたはLINQを使用することができます。いくつかの並べ替えのIEnumerableにテーブル全体を取得し、LINQを使用します。この方法は、O(1)代わりのO(n)なります含まれているため、あなたのlst_TermIdがHashSet<int>ある場合は、より良いパフォーマンスが得られます

static IEnumerable<int> Get_ExId_List(ICollection<int> lst_TermId) 
{ 
    //this is just for the example - get the real data instead 
    var data = new[] { 
     new { Ex_Id = 1, Term_Id = 2}, 
     new { Ex_Id = 1, Term_Id = 3}, 
     new { Ex_Id = 1, Term_Id = 4}, 
     new { Ex_Id = 1, Term_Id = 5}, 
     new { Ex_Id = 2, Term_Id = 2}, 
     new { Ex_Id = 3, Term_Id = 2}, 
     new { Ex_Id = 3, Term_Id = 4}, 
    }; 

    return data 
     .Where(row => lst_TermId.Contains(row.Term_Id)) 
     .GroupBy(row => row.Ex_Id) 
     .Where(group => group.Count() == lst_TermId.Count()) 
     .Select(group => group.Key); 
} 

static void Main(string[] args) 
{ 
    HashSet<int> lst_TermId = new HashSet<int>(); 
    lst_TermId.Add(2); 

    Console.WriteLine(); 
    var result = Get_ExId_List(lst_TermId); 
    foreach (var exid in result) 
     Console.WriteLine(exid); 

    lst_TermId.Add(4); 

    Console.WriteLine(); 
    result = Get_ExId_List(lst_TermId); 
    foreach (var exid in result) 
     Console.WriteLine(exid); 

    lst_TermId.Add(3); 

    Console.WriteLine(); 
    result = Get_ExId_List(lst_TermId); 
    foreach (var exid in result) 
     Console.WriteLine(exid); 
} 

注: はここでの例です。

+0

私は.Net 2.0を使用しています。これは正しく動作しません。 – nawfal

+0

そうそう、あなたはLINQのために3.5以上が必要... –

+0

しかし、いずれにせよ、これは家庭での使用の.Net 4でIを考慮して、私のために有用である:) – nawfal

関連する問題