根据多对多关系过滤结果

时间:2010-09-19 18:09:45

标签: .net sql-server many-to-many

我想过滤一个查询的结果,该查询返回两个表中的结果,这两个表之间有很多关系。 请考虑以下情形:(SQL Server或MS Access)
表:学生
    --StudentID
    --StudentName

表:成绩
     - 学生(外键)
    --CourseID(外键。为了简单而忽略)
    --StudentGrade(满分100分)

现在我想过滤结果并仅返回成绩均为>的学生的成绩详情。 50。 现在,我采取了以下步骤:
1 - 获取所有学生和成绩:

DataTable dtAll = GetData("SELECT * FROM Students INNER JOIN Grades ON Students.StudentID = Grades.StudentID)  

2 - 让所有至少有一个成绩的学生< 50.(学生失败)

    DataTable dtFailed = GetData("SELECT Distinct(Students.StudentID), Grades.StudentGrade FROM Students INNER JOIN INNER JOIN Grades ON Students.StudentID = Grades.StudentID WHERE Grades.StudentGrade < 50")  

3 - 删除与失败学生相关的所有字段:

foreach (DataRow failedRow in dtFailed.Rows)
        {
            int counter = 0;
            while (counter < dtAll.Rows.Count)
            {
                if (counter >= dtAll.Rows.Count)
                    break;
                curRow = dtAll.Rows[counter];

                if (Convert.ToInt32(curRow["StudentID"]) == Convert.ToInt32(failedRow["StudentlID"]))
                    dtAll.Rows.Remove(curRow);
                else
                    counter += 1;
            }
        }  

这段代码只是遍历所有dtFailed行,并删除dtAll中的行,这些行在dtFailed中有一个条目。 (如果学生至少有一门课程失败,所有学生的成绩将被删除。) 我想这是生产环境中的常见情况,希望有更快更清洁的方法。 感谢是否有人与我分享。
附:如果只能通过存储过程或任何特定于SQL的方式(不可访问)来完成,请分享,因为我可以根据需要使用SQL Server而不是MS Access。

2 个答案:

答案 0 :(得分:1)

SELECT s.StudentId  ,
       s.StudentName,
       g.StudentGrade
FROM   Students s
       JOIN Grades g
       ON     g.StudentID = s.StudentID
WHERE  g.StudentGrade     > 50
AND    NOT EXISTS
       (SELECT *
       FROM    Grades g2
       WHERE   g2.StudentGrade <= 50
       AND     g.StudentID   = g2.StudentID)

答案 1 :(得分:1)

也许使用LINQ查询dtAll而不是再次访问数据库?

//student IDs having min grade greater than 50
 var studentIDs = from f in table.AsEnumerable()
                         group f by new { StuID = f.Field<int>("StudentID"), 
                                       StuGrade = f.Field<int>("StudentGrade") } 
                         into g
                         where g.Min(x => x.Field<int>("StudentGrade") > 50)
                         select new
                         {
                             StudentID = g.Key.StuID,
                             StudentGrade = g.Key.StuGrade
                         };


foreach (var item in studentIDs)
{
    Console.WriteLine(item.StudentID + " : " + item.StudentGrade);
}