Мне нужно изменить способ хранения информации в БД. Потому что запрос работает медленно с старой моделью, которую я разработал.
Общая проблема следующая.
1) У меня есть список курсов, и у каждого курса есть список тегов, описывающих общее содержание курса. Например, курс под названием «Системы управления базами данных » может иметь следующие теги: { sql, index, key, relation }.
2) У меня есть профессора, у которых есть теги, которые обычно описывают, чему они учат в своих курсах. Например, Barton {sql, php, apache, mysql}
Мне нужно найти всех преподавателей в БД, которые наилучшим образом соответствуют конкретному выбранному курсу. Также мне нужно отсортировать их по их весу соответствия.
Вопрос
Вопрос заключается в том, как хранить эту информацию в БД и как обрабатывать эту сохраненную информацию для решения этой проблемы.
Этот вопрос появился после того, как я получил массу негативных критических замечаний по поводу моего запроса sql здесь .
Ну, я бы начал с чего-то вроде этих 5 таблиц:
Course (CourseID, CourseName, ...) Professor (ProfID, ProfName, ...) Tag (TagID, TagName) CourseTag (CourseID, TagID) ProfTag (ProfID, TagID)
и запросите его что-то вроде
SELECT ProfName, Count(PT.TagID) AS Weighting FROM Professor P INNER JOIN ProfTag PT ON P.ProfID = PT.ProfID INNER JOIN CourseTag CT ON PT.TagID = CT.TagID WHERE CT.CourseID = @SelectedCourse GROUP BY ProfName
Это синтаксис MS SQL Server … не знаю, что вы используете (но с php, возможно, не так :))
Похоже, вы должны иметь следующие таблицы:
Course
– перечисляет курсы. Subject_area
– список тем, которые могут охватывать курсы, такие как «sql», «c ++» и т. Д. Course_content
– перекрестная справочная таблица между Course
и Subject_area
. Professor
– перечисляет профессоров. Professor_expertise
– перекрестная справочная таблица между Professor
и Subject_area
. Например, у вас может быть профессор «Проф. Браун» с соответствующей строкой в таблице « Professor
, а также тематические области, называемые «sql», «java» и «алгоритмы оптимизации», каждый из которых интересуется профессором Брауном. для каждой из этих областей в Professor_expertise
будет соответствующая строка, и каждый из них будет ссылаться на строку профессора Брауна в таблице Professor
, а также соответствующую строку в таблице Subject_area
.
Теперь предположим, что у вас есть курс «SQL и дизайн базы данных», и в нем есть области «Дизайн базы данных», «SQL», «Индексы базы данных», «Нормализация» и «Оптимизация запросов». Вы могли видеть, какие профессора подходят для обучения курсу, выпуская
SELECT Professor.Name, Professor.Id, MySubquery.NumMatches FROM Professor JOIN ( SELECT Professor, COUNT(*) AS NumMatches FROM Professor_expertise WHERE Subject_area_id IN ( SELECT Course_content.Subject_area_Id FROM Course_content WHERE Course_content.Course_Id = x ) GROUP BY Professor ) AS MySubquery ORDER BY MySubquery.NumMatches DESC
где x
– идентификационный номер, соответствующий курсу.
Вот что я предлагаю в качестве вашей схемы (первичные ключи выделены жирным шрифтом):
id
и name
id
и name
id
и name
tag_id
и course_id
(индекс на tag_id
для ускорения запроса) tag_id
и prof_id
(индекс на tag_id
для ускорения запроса) Тогда вы можете так:
SELECT profs.id, COUNT(*) AS matches FROM profs, profTags, courseTags WHERE profs.id=profTags.prof_id AND profTags.tag_id=courseTags.tag_id AND courseTags.course_id=[COURSE ID] GROUP BY profs.id ORDER BY matches DESC;
Этот запрос возвращает список идентификаторов prof, упорядоченных по количеству совпадений тегов.
В простейшей форме я бы предложил иметь 5 таблиц:
tbl_CourseList
CourseId – int, PK, identity
Название курса – varchar (100)
tbl_CourseContent
ContentId – int, PK, identity
CourseId – int, FK
Тип – варчар (25)
tbl_Professors
ProfessorId – int, PK, identity
ProfessorName – varchar (100)
tbl_ProfessorExpertise
ExpertiseId – int, PK, identity
ProfessorId – int, FK
ЭкспертизаТип – варчар (25)
ExpertiseWeight – int
tbl_ProfessorCourses
CourseId
ProfessorId
Надеюсь, это самоочевидно …