1

Ex_Id と Term_Id の 2 つの列を持つテーブルがあり、どちらも int 型です。私のテーブルには、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>
}

つまり、ターム ID のリストを渡し、いくつかの基準に一致するエクササイズ 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]
}

クエリの部分は私の混乱です。この条件でのクエリはどのようなものでしょうか? 私が管理できる残りの部分。質問が明確であることを願っています。ありがとう..

4

2 に答える 2

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(DISTINCT Term_ID)ますCOUNT(*)

これは関係分割の問題です。「標準的な」解決策は、2 つのネガ (NOT EXISTS) を使用することです。

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
                  )
        ) 

于 2011-07-26T06:37:06.460 に答える
1

LINQ を使用できます。テーブル全体をある種の IEnumerable に取得してから、LINQ を使用します。次に例を示します。

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);
}

lst_TermId が の場合HashSet<int>、contains メソッドがO(1)の代わりになるため、パフォーマンスが向上することに注意してくださいO(n)

于 2011-07-26T06:50:23.783 に答える