改进我的SQL Select语句以选择尚未完全完成某个部分的学生

时间:2015-06-17 22:05:26

标签: sql sql-server linq tsql

我的SQL技能非常有限。我是技术学院计算机科学的第二年。我正在构建一个Windows窗体应用程序,允许我学院的BAS主管跟踪学生及其在整个课程中的进度。我完全可以控制数据库设计,所以如果你想到一种方法来帮助我找到一个可能涉及调整数据库的解决方案。

我正在尝试在Students EnrollmentStatus Courses的所有CreditSection中选择没有1 3的所有CreditSection }}。共有12门课程1 SELECT * FROM Students WHERE each student has 12 entries in CourseEnrollment AND CourseEnrollment.EnrollmentStatus = 3 AND Courses.CreditSection = 1

我正在使用的表格如下: Schema

我可以想出几种方法来获得我的解决方案,但似乎无法将它们写成SQL:

SELECT * FROM Students WHERE Courses.CourseID 1 thru 12 EXIST in
CourseEnrollment for each student AND CourseEnrollment.EnrollmentStatus = 3

SELECT DISTINCT s.* FROM Students s
WHERE s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 1 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 2 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 3 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 4 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 5 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 6 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 7 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 8 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 9 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 10 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 11 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 12 AND ce.EnrollmentStatus = 3) OR
s.StudentID NOT IN (SELECT ce.StudentID FROM CourseEnrollment ce WHERE ce.CourseID = 13 AND ce.EnrollmentStatus = 3)

我可以使用下面的这个混乱来达到理想的解决方案,但是当我检查已经完成了4年课程的学生时...这个查询变得非常漫长并且可能消耗大量资源。

此查询选择不在已完成一门或多门课程的学生列表中的学生:

var query =
                from student in datStudents.Students.AsEnumerable<dsStudentManager.StudentsRow>()
                where !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 1 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 2 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 3 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 4 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 5 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 6 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 7 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 8 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 9 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 10 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 11 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 12 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID) ||
                !(from ce2 in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() where ce2.CourseID == 13 && ce2.EnrollmentStatus == 3 select ce2.Field<int>("StudentID")).Contains<int>(student.StudentID)
                select new
                {
                    id = student.StudentID,
                    rtcid = student.RTCStudentID,
                    firstname = student.FirstName,
                    lastname = student.LastName,
                    phone = student.Phone,
                    studentemail = student.StudentEmail,
                    personalemail = student.PersonalEmail,
                    address = student.Address,
                    city = student.City,
                    state = student.State,
                    zip = student.Zip,
                    birthdate = student.BirthDate,
                    gender = student.Gender,
                    notes = student.Notes,
                    studentdocumentslocation = student.StudentDocumentsLocation
                };

我的目标是弄清楚如何在SQL中编写此查询,然后将其转换为LINQ,这最终是我需要的。如果有人可以帮助解决这一问题,我将不胜感激。

我已将上述内容转换为LINQ,它看起来同样可怕:

    MenuItem searchMenuItem = menu.findItem(R.id.action_search);
    if (Utils.hasIceCreamSandwich())
        searchMenuItem.expandActionView();
    else MenuItemCompat.expandActionView(searchMenuItem);

3 个答案:

答案 0 :(得分:4)

使用带有group by和having语句的子查询,你可以得到类似的东西:

 SELECT * FROM Students WHERE StudentID NOT IN (
      SELECT s.StudentID FROM Students s 
        JOIN CourseEnrollment ce ON s.StudentID = ce.StudentID
        JOIN Courses c ON ce.CourseID = c.CourseID
        WHERE ce.EnrollmentStatus = 3 AND c.CreditSection = 1
        GROUP BY s.StudentID
        HAVING COUNT(*) = 12
      )

内部查询构建了学生返回的标准,“HAVING COUNT(*)= 12”可以让学生找到匹配12门课程的学生。如果您只是课程的一部分,您也可以尝试以下方法。

 SELECT * FROM Students WHERE StudentID NOT IN (
      SELECT s.StudentID FROM Students s 
        JOIN CourseEnrollment ce ON s.StudentID = ce.StudentID
        JOIN Courses c ON ce.CourseID = c.CourseID
        WHERE ce.EnrollmentStatus = 3 AND c.CreditSection = 1
        AND c.CourseID IN (1,2,3,4,5,6,7,8)
        GROUP BY s.StudentID
        HAVING COUNT(*) = 8 -- Number of courses in the ID in clause
      )

希望这有助于您走上正轨。

答案 1 :(得分:2)

尝试这样的东西,我手工打字,所以可能会有拼写错误。

SELECT * FROM Students s
	inner join (select StudentID, count(0) as CrsEnrollCount
					from CourseEnrollment ce 
					inner join Courses c 
					on ce.CourseID = c.CourseID
					where ce.EnrollmentStatus = 3 AND Courses.CreditSection = 1) cnt
	on cnt.StudentID = s.StudentID
where CrsEnrollCount < 12

答案 2 :(得分:0)

对于记录,这个T-SQL:

SELECT * FROM Students WHERE StudentID NOT IN (
  SELECT s.StudentID FROM Students s 
    JOIN CourseEnrollment ce ON s.StudentID = ce.StudentID
    JOIN Courses c ON ce.CourseID = c.CourseID
    WHERE ce.EnrollmentStatus = 3 AND c.CreditSection = 1
    GROUP BY s.StudentID
    HAVING COUNT(*) = 12
  )

成为这个LINQ:

var query = 
            from student in datStudents.Students.AsEnumerable<dsStudentManager.StudentsRow>()
            where !(from s2 in datStudents.Students.AsEnumerable<dsStudentManager.StudentsRow>()
                        join ce in datStudents.CourseEnrollment.AsEnumerable<dsStudentManager.CourseEnrollmentRow>() on student.StudentID equals ce.StudentID
                        join c in datStudents.Courses.AsEnumerable<dsStudentManager.CoursesRow>() on ce.CourseID equals c.CourseID
                        where ce.EnrollmentStatus == 3 && c.CreditSection == 1
                        group s2 by s2.StudentID into s3
                        where s3.Count() == 12
                        select s3.Key).Contains<int>(student.StudentID)
            select new
            {
                id = student.StudentID,
                rtcid = student.RTCStudentID,
                firstname = student.FirstName,
                lastname = student.LastName,
                phone = student.Phone,
                studentemail = student.StudentEmail,
                personalemail = student.PersonalEmail,
                address = student.Address,
                city = student.City,
                state = student.State,
                zip = student.Zip,
                birthdate = student.BirthDate,
                gender = student.Gender,
                notes = student.Notes,
                studentdocumentslocation = student.StudentDocumentsLocation
            };

据我所知,这是正确的。无论如何,它会产生预期的效果。