Предположим, у нас есть очень простая таблица:
|class |student|
---------------
Math Alice
Math Bob
Math Peter
Math Anne
Music Bob
Music Chis
Music Debbie
Music Emily
Music David
Sports Alice
Sports Chris
Sports Emily
.
.
.
Теперь я хочу выяснить, с кем у меня больше всего общих классов.
Поэтому в основном я хочу запрос, который получает в качестве входных данных список классов (некоторое подмножество всех классов)
и возвращает список вроде:
|student |common classes|
Brad 6
Melissa 4
Chris 3
Bob 3
.
.
.
То, что я сейчас делаю, - это отдельный запрос для каждого класса. Слияние результатов производится на стороне клиента. Это очень медленно, потому что я очень трудолюбивый ученик и посещаю около 1000 уроков - как и большинство других учеников. Я хотел бы сократить транзакции и выполнить обработку на стороне сервера, используя хранимые процедуры. Я никогда не работал с sprocs, поэтому я был бы рад, если бы кто-нибудь дал мне несколько советов, как это сделать.
(примечание: я использую кластер MySQL, потому что это очень большая школа с 1 миллионом классов и несколькими миллионами учеников)
UPDATE
Хорошо, очевидно, что я не эксперт по БД;) 4 раза почти такой же ответ означает, что это слишком просто.
В любом случае, спасибо! Я протестировал следующий оператор SQL, и он возвращает то, что мне нужно, хотя он очень медленный в кластере (но это будет другой вопрос, я думаю).
SELECT student, COUNT(class) as common_classes
FROM classes_table
WHERE class in (my_subject_list)
GROUP BY student
ORDER BY common_classes DESC
Но на самом деле я слишком сильно упростил свою задачу, поэтому давайте немного усложним:
Некоторые классы важнее других, поэтому они имеют вес:
| class | importance |
Music 0.8
Math 0.7
Sports 0.01
English 0.5
...
Кроме того, студенты могут быть более или менее важными.
(Если вам интересно, о чем все это ... это аналогия. И она становится все хуже. Поэтому, пожалуйста, просто примите этот факт. Это связано с нормализацией.)
|student | importance |
Bob 3.5
Anne 4.2
Chris 0.3
...
Это означает, что простой COUNT () больше не будет этого делать.
Чтобы выяснить, с кем у меня больше всего общего, я хочу сделать следующее:
map<Student,float> studentRanking;
foreach (Class c in myClasses)
{
float myScoreForClassC = getMyScoreForClass(c);
List students = getStudentsAttendingClass(c);
foreach (Student s in students)
{
float studentScoreForClassC = c.classImportance*s.Importance;
studentRanking[s] += min(studentScoreForClassC, myScoreForClassC);
}
}
Надеюсь, это не слишком запутанно.
Я должен также упомянуть, что меня нет в базе данных, поэтому я должен сообщить оператору SELECT / хранимой процедуре, какие классы я посещаю.