StudentsOfFaculti are students. contextDB.tableBalli is the scores of students in different disciplines. The tables are linked by ID_Studenta. I find students who have more than 40 points in all disciplines. If a student has at least one discipline less than 40, then I miss this student. I do not know how to write a linq request to have the same result.

int AbsolutnayaUspevaemost = 0; foreach (var ksf in StudentsOfFaculti) { foreach (var b in contextDB.tableBalli) { if (ksf.ID == b.ID_Studenta && b.Itog >= 41) { } else { AbsolutnayaUspevaemost--; break; } } AbsolutnayaUspevaemost++; } 
  • Ahhhh! Quadratic queries! - VladD
  • @VladD, uh ... explain? - Grundy
  • one
    And what does this query do? some kind of strange logic - Grundy
  • StudentsOfFaculti are students of contextDB.tableBalli are points of students in different disciplines. I find students who have more than 40 points in all disciplines. If a student has at least one discipline less than 40, then I miss this student. - Vivus
  • add explanations to the question itself: edit - Grundy

3 answers 3

So far, this decision has been realized - it gives the number of those who are not succeeding:

 using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { List<Student> students = new List<Student> { new Student { ID = 0 }, new Student { ID = 1 }, new Student { ID = 2 }, new Student { ID = 3 }, new Student { ID = 4 }, new Student { ID = 5 }, new Student { ID = 6 }, new Student { ID = 7 }, new Student { ID = 8 }, new Student { ID = 9 } }; List<Mark> marks = new List<Mark> { new Mark { ID_Studenta = 0, Itog = 41 }, new Mark { ID_Studenta = 0, Itog = 48 }, new Mark { ID_Studenta = 0, Itog = 43 }, new Mark { ID_Studenta = 1, Itog = 40 }, new Mark { ID_Studenta = 1, Itog = 41 }, new Mark { ID_Studenta = 1, Itog = 28 }, new Mark { ID_Studenta = 2, Itog = 50 }, new Mark { ID_Studenta = 2, Itog = 55 }, new Mark { ID_Studenta = 2, Itog = 59 }, new Mark { ID_Studenta = 3, Itog = 30 }, new Mark { ID_Studenta = 3, Itog = 29 }, new Mark { ID_Studenta = 3, Itog = 36 }, new Mark { ID_Studenta = 4, Itog = 48 }, new Mark { ID_Studenta = 4, Itog = 46 }, new Mark { ID_Studenta = 4, Itog = 42 }, new Mark { ID_Studenta = 5, Itog = 41 }, new Mark { ID_Studenta = 5, Itog = 40 }, new Mark { ID_Studenta = 5, Itog = 43 }, new Mark { ID_Studenta = 6, Itog = 39 }, new Mark { ID_Studenta = 6, Itog = 42 }, new Mark { ID_Studenta = 6, Itog = 46 }, new Mark { ID_Studenta = 7, Itog = 30 }, new Mark { ID_Studenta = 7, Itog = 30 }, new Mark { ID_Studenta = 7, Itog = 50 }, new Mark { ID_Studenta = 8, Itog = 45 }, new Mark { ID_Studenta = 8, Itog = 46 }, new Mark { ID_Studenta = 8, Itog = 49 }, new Mark { ID_Studenta = 9, Itog = 40 }, new Mark { ID_Studenta = 9, Itog = 38 }, new Mark { ID_Studenta = 9, Itog = 48 } }; int c = students.Join(marks, s => s.ID, m => m.ID_Studenta, (s, m) => new { id = s.ID, itog = m.Itog }) .Where(a => a.itog < 41) .GroupBy(a => a.id) .Count(); Console.WriteLine(c); } } class Student { public long ID { get; set; } } class Mark { public long ID_Studenta { get; set; } public int Itog { get; set; } } 

A more competent solution could be given to you by SQL specialists. Perhaps you should add such a label here.

  • Unfortunately, it is not working properly yet. Take for example a student with ID_Studenta = 7 from Andrei’s example. This student has 3 values ​​of 30, 30 and 50, that is, 2 values ​​he has less than forty (I’ll make a reservation that I changed the condition to .Where (a => a.itog> 41) and it is not necessary to count it. But it considers the request. The request should consider the student if all values ​​are greater than 40. If at least one value is less than 40, then he should not count it. - Vivus
  • @Vivus if the decision does not suit you, why put the mark "Accepted"? It is confusing. - user227049
  • one
    @Vivus judging by your comment, just use the following query: marks.GroupBy(mark => mark.ID_Studenta).Where(group => group.All(value => value.Itog >= 41)).Count(); - user227049
  • Well, if you change the condition, then, of course, it will not work correctly, but if your goal is just to determine the number of those who are in progress, consider it as mine, then deduct it from the total. If the final goal is to get exactly the collection of the achievers, then my option will not work for you. - Andrei NOP

Returns the number of students whose all grades exceed the threshold of 40 points.

 class Student { public int Id { get; set; } } class Mark { public int StudentId { get; set; } public int Value { get; set; } } ... var threshold = 40; var count = students .Join(marks, x => x.Id, x => x.StudentId, (x, y) => new { StudentId = x.Id, StudentMark = y.Value }) .GroupBy(x => x.StudentId) .Where(x => !x.Any(y => y.StudentMark <= threshold)) .Count(); 

If in the table with grades there are no grades of any "left" students who are not in the students' table, then Join can be eliminated as an extra operation:

 var count = marks .GroupBy(x => x.StudentId) .Where(x => !x.Any(y => y.Value <= threshold)) .Count(); 

But, in general, there is something badly wrong in the logic of your loop. We find ourselves in the body of the else condition in two cases:

  • some student's assessment is unsatisfactory;
  • it is generally the assessment of some other student, not the one we are considering at the moment.

Thus, the cycle is interrupted and the resulting value decreases each time we just stumble on the wrong student. To prevent this from happening, the cycle can be rewritten approximately as follows:

 var result = 0; foreach (var student in students) { result += 1; // foreach (var mark in marks.Where(x => x.StudentId == student.Id)) { if (mark.Value <= threshold) { result -= 1; break; } } } 

    The same option as @Andrey, but in a different style:

     int c = (from mark in marks from student in students where mark.ID_Studenta == student.ID && mark.Itog < 41 group student by student.ID).Count(); 

    Option with Join

     int c = (from mark in marks join student in students on mark.ID_Studenta equals student.ID where mark.Itog < 41 group student by student.ID).Count(); 
    • Unfortunately here is the same thing that I described above. - Vivus