Виртуальная группа (одна на каждый факультет) в таблице `group` c FK на faculty.
Помещать туда студентов без группы.
В таблицу `group` добавить колонку с типом группы (обычная или имеет особый смысл).
30.10.2024 16:26, Pavel Dvorkin пишет:
PD> Да, учебная, но все же хотелось бы знать наилучшее решение в рамках SQL.
очень сильно зависит от "академичности" препода.
если он фанат К.Дж.Дейта, то это одно, а если Дж.Грея, то совсем другое.
если есть методичка, следуй указаниям, и не парься.
а то сделаешь слишком умно — препод не поймёт...
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Но это уже совсем другая задача.
Ты бы начал с формализации требований/ТЗ/спецификаций (назови как хочешь) для твоей учебной задачи -- основные моменты без растекания.
Например, если в требованиях будет зафиксированно, что студент может быть только в одной группе и историю переводов из группы в группу, или с факультета на факультет хранить не надо, то и вопросов меньше.
Да и проверять и оценивать работы студентов будет проще.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>То есть когда студент становится студентом вне группы, Student.GroupID ставится в NULL ? А что тогда получится с первым FK ?
Ничего особенного. Если один из компонентов FK null, то он не проверяется.
Я же дал ссылку — нажмите на неё.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Павел, ты пытаешься смешивать в кучу атрибуты сущностей и соотношения между сущностями.
По классике, нужны таблицы соотношений, а не ссылки на другие сущности.
Но если это задача из типа "учебных", то и не парься.
Как сделаешь, так и будет.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Пусть та же система, что и тут
PD>На императивном языке можно было бы ограничиться одной ссылкой на некий интерфейс или базовый класс. Если студент член группы, то на Group (а она на Faculty), если не член — прямо на Faculty. Может, и не лучшее решение, но возможное. А тут одним FK можно обойтись ?
Можно, имитация наследования. Базовая таблица для факультета и группы, к ней 1 к 1 таблицы факультета и группы и у студента внешний ключ на нее, в зависимости от ситуации это будет или факультет или группа.
Здравствуйте, Alex.Che, Вы писали:
AC>очень сильно зависит от "академичности" препода. AC>если он фанат К.Дж.Дейта, то это одно, а если Дж.Грея, то совсем другое. AC>если есть методичка, следуй указаниям, и не парься. AC>а то сделаешь слишком умно — препод не поймёт...
Я и есть тот самый "препод", и хотел получить мнение коллег о том, какое решение они считают лучшим , чтобы рекомендовать именно его.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>В итоге у студента должно быть 2 FK — на группу и факультет. Но группа имеет FK на факультет. Получается, что студент фактически имеет 2 FK на факультет — один явно, а другой косвенно, через свой FK на группу и FK группы на факультет.
Дополню, что студет может одновременно учиться на двух (и более) факультетах.
В нашем пединституте можно было например паралельно с физматом обучаться на инязе.
Закон разрешает студентам одновременно осваивать несколько образовательных программ.
Еще комментарий по первоначальному варианту. С начала нужно разобраться: А есть ли тут проблема вообще? Большинство сделают так: один fk у студента постоянно указывает на факультет, в который он зачислен, второй на группу если он в ней учится. Казалось бы тут есть избыточность: студент имеет имеет две связи с факультетом: одну прямую, вторую через группу. Но, это разные ассоциации. Что бы это определить нужно попытаться им дать названия и(или) назвать роли сущностей участвующих в ассоциации. В первом случае у студента роль "зачисленный", а во втором "учащийся". Группу можно считать сущностью-ассоциацией. Еще к этому есть инвариант: студент может учиться только в той группе, которая связана с факультетом в который он зачислен. Можно привести и другие примеры когда между сущностями могу существовать более чем одной ассоциации: между мужчиной и женщиной могут существовать две связи: муж и жена, начальник — подчиненный(встречал такое в жизни). Надеюсь понятно изложил.
PD>Вот только с UNION вопрос. Таблицы-то сильно разные. В них вообще может не быть одинаковых по смыслу полей, кроме ID, и то, если он в них есть(они могли бы использовать ID базовой как свой PK). Что брать-то ? И как потом определить, откуда взяли ?
Сорри, если не к месту вмешиваюсь и вообще уже поздно, но здесь я не понял — причём тут UNION, когда нужны просто два LEFT JOIN (или три для добавления в выборку данных по факультету в случае, когда студент в группе):
select * from students s --вместо звездочки - нужные поля, естественно, разные из groups и faculties.inner join facs_groups fg on s.fac_group_id=fg.id --джойн с базовой таблицей групп/факультетовleft join faculties f on f.id=fg.id --факультет; выбираемые поля f.* будут NULL, если студент в группеleft join groups g on g.id=fg.id --группа; выбираемые поля g.* будут NULL, если студент НЕ в группеleft join faculties ff on g.fac_id=ff.id --факультет по группе; выбираемые поля ff.* будут NULL, если студент НЕ в группе
поля по факультету, чтобы не дублировать в выборке f.* и ff.*, логично выбирать через COALESCE(f.поле, ff.поле) AS поле
BTW, оставаясь в рамках ООП-идеологии, для исключения "лишней по Оккаму" базовой таблицы можно посчитать группу базовым классом, а факультет — его наследником, и в результате получится точно такая же структура данных, что и в решении с "псевдогруппами для студентов без группы" — т.е. "псевдогруппа" и "факультет как его предок, т.е. группа" — это по сути одна и та же сущность.
(И тогда вышеприведенный запрос упрощается с четырех JOIN до всего двух, а это явный выигрыш!)
пусть есть таблица institute с одной строкой. Или как-то иначе. Это здесь не обсуждаем.
Есть факультеты. Таблица faculty с FK (или без него, как хотите) на institute
На факультете есть группы. Таблица `group` с FK на faculty.
А еще есть студенты. Таблица student и вот тут вопрос
Студент входит в группу, но ей не принадлежит. После приказа ректора о зачислении он на короткое время становится студентом вне группы, пока его в группу декан не определит. Если уйдет в академотпуск, то до возвращения из него будет опять студентом вне группы.
Значит, FK на `group' с разрешением NULL и с ON DELETE SET NULL. Допустим.
Но если он не в группе, то он все же на факультете. Впрочем, если и в группе, то тоже.
Получается еще один FK на faculty, и тут уже без разрешения NULL, так как вне факультета он быть не может.
В итоге у студента должно быть 2 FK — на группу и факультет. Но группа имеет FK на факультет. Получается, что студент фактически имеет 2 FK на факультет — один явно, а другой косвенно, через свой FK на группу и FK группы на факультет.
Убрать его явный FK на факультет нельзя — при выходе из группы он станет не пойми какого факультета.
Убрать его FK на группу тоже нельзя.
На императивном языке можно было бы ограничиться одной ссылкой на некий интерфейс или базовый класс. Если студент член группы, то на Group (а она на Faculty), если не член — прямо на Faculty. Может, и не лучшее решение, но возможное. А тут одним FK можно обойтись ?
Здравствуйте, Pavel Dvorkin, Вы писали: PD>На императивном языке можно было бы ограничиться одной ссылкой на некий интерфейс или базовый класс. Если студент член группы, то на Group (а она на Faculty), если не член — прямо на Faculty. Может, и не лучшее решение, но возможное. А тут одним FK можно обойтись ?
Одним FK можно, но не одной таблицей. Нужна новая сущность — студенты без групп с FK на факультет.
Здравствуйте, Qt-Coder, Вы писали:
QC>Одним FK можно, но не одной таблицей. Нужна новая сущность — студенты без групп с FK на факультет.
Существенно усложнит запросы. Если принадлежность или нет к группе не существенна в запросе, то придется делать что-то вроде UNION в лучшем случае, а в худшем 2 запроса.
Плюс исключение/добавление в группу превратится из простого UPDATE к переносу
Здравствуйте, Qulac, Вы писали:
Q>Можно, имитация наследования. Базовая таблица для факультета и группы, к ней 1 к 1 таблицы факультета и группы и у студента внешний ключ на нее, в зависимости от ситуации это будет или факультет или группа.
Как юмор оценил, а если серьезно
Плюс дискриминатор в этой таблице , чтобы отличать группы от факультетов
Плюс не знаю какие CONSTRAINT или еще что-то, чтобы группы не включались в группы, факультеты в группы или факультеты, а только группы в факультеты.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Qulac, Вы писали:
Q>>Можно, имитация наследования. Базовая таблица для факультета и группы, к ней 1 к 1 таблицы факультета и группы и у студента внешний ключ на нее, в зависимости от ситуации это будет или факультет или группа.
PD>Как юмор оценил, а если серьезно
Это не юмор был.
PD>Плюс дискриминатор в этой таблице , чтобы отличать группы от факультетов
Это за чем?
PD>Плюс не знаю какие CONSTRAINT или еще что-то, чтобы группы не включались в группы, факультеты в группы или факультеты, а только группы в факультеты.
А не будет проблем, fk группы будет указывать на факультет, а не на базовую таблицу.
Здравствуйте, Qulac, Вы писали:
Q>>>Можно, имитация наследования. Базовая таблица для факультета и группы, к ней 1 к 1 таблицы факультета и группы и у студента внешний ключ на нее, в зависимости от ситуации это будет или факультет или группа.
Q>Это не юмор был.
А зачем тогда смайлик поставил ?
PD>>Плюс дискриминатор в этой таблице , чтобы отличать группы от факультетов
Q>Это за чем?
Ну этот тот же instanceof.
Получил по студенческому FK элемент из базовой таблицы, а теперь куда второй запрос ? На факультет или группу ?
PD>>Плюс не знаю какие CONSTRAINT или еще что-то, чтобы группы не включались в группы, факультеты в группы или факультеты, а только группы в факультеты.
Q>А не будет проблем, fk группы будет указывать на факультет, а не на базовую таблицу.
То есть у группы будет 2 FK — на факультет и на базовую таблицу ?
M>>Виртуальная группа (одна на каждый факультет) в таблице `group` c FK на faculty.
PD>Наверное, все же не в таблице группы, а на факультете ?
Нет, именно в таблице `group`. Студент без группы будет иметь FK на такую виртуальную группу.
PD>Ответил на аналогичное здесь PD>https://rsdn.org/forum/db/8843915.1
Здравствуйте, m2user, Вы писали:
M>Нет, именно в таблице `group`. Студент без группы будет иметь FK на такую виртуальную группу.
M>В предлагаемом мной варианте не добавляется новых таблиц. M>Перенос студента между группами в т.ч. в состояние "без группы" будет в один update.
Теперь понял. Похоже, это и впрямь наилучшее решение.
Меня смутил термин "виртуальная". Просто группа тех, кто не в обычной группе.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Qulac, Вы писали:
Q>>>>Можно, имитация наследования. Базовая таблица для факультета и группы, к ней 1 к 1 таблицы факультета и группы и у студента внешний ключ на нее, в зависимости от ситуации это будет или факультет или группа.
Q>>Это не юмор был.
PD>А зачем тогда смайлик поставил ?
Я его всегда ставлю.
PD>>>Плюс дискриминатор в этой таблице , чтобы отличать группы от факультетов
Q>>Это за чем?
PD>Ну этот тот же instanceof.
PD>Получил по студенческому FK элемент из базовой таблицы, а теперь куда второй запрос ? На факультет или группу ?
На ту таблицу где есть соответствующая строка в fk на ключ.
PD>>>Плюс не знаю какие CONSTRAINT или еще что-то, чтобы группы не включались в группы, факультеты в группы или факультеты, а только группы в факультеты.
Q>>А не будет проблем, fk группы будет указывать на факультет, а не на базовую таблицу.
PD>То есть у группы будет 2 FK — на факультет и на базовую таблицу ?
Здравствуйте, Qulac, Вы писали:
PD>>А зачем тогда смайлик поставил ?
Q>Я его всегда ставлю.
Я же не знал В ответе он был один, было бы много — может, и догадался бы.
PD>>>>Плюс дискриминатор в этой таблице , чтобы отличать группы от факультетов
Q>>>Это за чем?
PD>>Ну этот тот же instanceof.
PD>>Получил по студенческому FK элемент из базовой таблицы, а теперь куда второй запрос ? На факультет или группу ?
Q>На ту таблицу где есть соответствующая строка в fk на ключ.
Где, в базовой таблице или в таблице группы или факультета ? Если в базовой, то там, значит, 2 FK и один из них NULL ? Если в таблице группы или факультета, то как мне узнать, в какой ?
PD>>>>Плюс не знаю какие CONSTRAINT или еще что-то, чтобы группы не включались в группы, факультеты в группы или факультеты, а только группы в факультеты.
PD>>То есть у группы будет 2 FK — на факультет и на базовую таблицу ?
Q>Да.
Здравствуйте, Alex.Che, Вы писали:
AC>Павел, ты пытаешься смешивать в кучу атрибуты сущностей и соотношения между сущностями. AC>По классике, нужны таблицы соотношений, а не ссылки на другие сущности. AC>Но если это задача из типа "учебных", то и не парься. AC>Как сделаешь, так и будет.
Да, учебная, но все же хотелось бы знать наилучшее решение в рамках SQL.
Здравствуйте, paucity, Вы писали:
P>С точки зрения нормализации, у тебя, возможно, должны быть таблицы: P>student P>group P>faculty P>student_group P>group_faculty
именно!
но видимо "таблицы отношений" ещё не проходили...
Здравствуйте, Pavel Dvorkin, Вы писали:
П>>Студенты без группы входят в группу студентов без группы
PD>Да. Это решение уже и предложено здесь
PD>https://rsdn.org/forum/db/8843919.1
Здравствуйте, paucity, Вы писали:
P>Для snapshot'а, а для отслеживания перехода студента из группы в группу?
UPDATE student SET group_id = target_group_id
Или ты что-то иное имеешь в виду под словом "отслеживание". Историю его нахождения в группах за весь курс обучения ? Тогда да, но об этом речи не было.
Здравствуйте, Alex.Che, Вы писали:
AC>студент имеет право обучаться более чем по одной специальности. AC>по крайней мере в РФ это так, согласно ФГОС от 2021г.
Вообще-то может, а в других случаях точно может (например, спортшкола). Однако в рамках заданной темы предполагается, что не может.
Здравствуйте, Pavel Dvorkin, Вы писали:
AC>>студент имеет право обучаться более чем по одной специальности. AC>>по крайней мере в РФ это так, согласно ФГОС от 2021г.
PD>Вообще-то может, а в других случаях точно может (например, спортшкола). PD>Однако в рамках заданной темы предполагается, что не может.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Qulac, Вы писали:
PD>>>А зачем тогда смайлик поставил ?
Q>>Я его всегда ставлю.
PD>Я же не знал В ответе он был один, было бы много — может, и догадался бы.
PD>>>>>Плюс дискриминатор в этой таблице , чтобы отличать группы от факультетов
Q>>>>Это за чем?
PD>>>Ну этот тот же instanceof.
PD>>>Получил по студенческому FK элемент из базовой таблицы, а теперь куда второй запрос ? На факультет или группу ?
Q>>На ту таблицу где есть соответствующая строка в fk на ключ.
PD>Где, в базовой таблице или в таблице группы или факультета ? Если в базовой, то там, значит, 2 FK и один из них NULL ?
Нет не значит.
Если в таблице группы или факультета, то как мне узнать, в какой ?
Сделать запрос.
PD>>>>>Плюс не знаю какие CONSTRAINT или еще что-то, чтобы группы не включались в группы, факультеты в группы или факультеты, а только группы в факультеты.
PD>>>То есть у группы будет 2 FK — на факультет и на базовую таблицу ?
Q>>Да.
PD>Сложновато.
PD>Решение вот тут мне кажется оптимальным.
PD>https://rsdn.org/forum/db/8843919.1
Здравствуйте, Qulac, Вы писали:
PD>>Где, в базовой таблице или в таблице группы или факультета ? Если в базовой, то там, значит, 2 FK и один из них NULL ?
Q>Нет не значит.
Q> Если в таблице группы или факультета, то как мне узнать, в какой ?
Q>Сделать запрос.
Ok, можно чуть подробнее ?
student имеет FK на базовую таблицу. Получили запись из нее, хорошо
На базовую ссылаются 2 таблицы : группа и факультет
Где FK ? В каждой из них на базовую ? А дискриминатора в базовой нет. В какую делать теперь запрос ? Или UNION предлагаешь ?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Qulac, Вы писали:
PD>>>Где, в базовой таблице или в таблице группы или факультета ? Если в базовой, то там, значит, 2 FK и один из них NULL ?
Q>>Нет не значит.
Q>> Если в таблице группы или факультета, то как мне узнать, в какой ?
Q>>Сделать запрос.
PD>Ok, можно чуть подробнее ?
PD>student имеет FK на базовую таблицу. Получили запись из нее, хорошо
PD>На базовую ссылаются 2 таблицы : группа и факультет
одно из двух: факультет или группа.
PD>Где FK ? В каждой из них на базовую ? А дискриминатора в базовой нет. В какую делать теперь запрос ? Или UNION предлагаешь ?
Да Union.
Программа – это мысли спрессованные в код
Re[10]: и еще один вопрос по реляционной структуре
PD>>student имеет FK на базовую таблицу. Получили запись из нее, хорошо
PD>>На базовую ссылаются 2 таблицы : группа и факультет
Q>одно из двух: факультет или группа.
Ну да, понятно.
PD>>Где FK ? В каждой из них на базовую ? А дискриминатора в базовой нет. В какую делать теперь запрос ? Или UNION предлагаешь ?
Q>Да Union.
Тогда понятно.
Вот только с UNION вопрос. Таблицы-то сильно разные. В них вообще может не быть одинаковых по смыслу полей, кроме ID, и то, если он в них есть(они могли бы использовать ID базовой как свой PK). Что брать-то ? И как потом определить, откуда взяли ?
With best regards
Pavel Dvorkin
Re[11]: и еще один вопрос по реляционной структуре
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Qulac, Вы писали:
PD>>>student имеет FK на базовую таблицу. Получили запись из нее, хорошо
PD>>>На базовую ссылаются 2 таблицы : группа и факультет
Q>>одно из двух: факультет или группа.
PD>Ну да, понятно.
PD>>>Где FK ? В каждой из них на базовую ? А дискриминатора в базовой нет. В какую делать теперь запрос ? Или UNION предлагаешь ?
Q>>Да Union.
PD>Тогда понятно.
PD>Вот только с UNION вопрос. Таблицы-то сильно разные. В них вообще может не быть одинаковых по смыслу полей, кроме ID, и то, если он в них есть(они могли бы использовать ID базовой как свой PK). Что брать-то ? И как потом определить, откуда взяли ?
В чем проблема нужный запрос написать, sql поддерживает условные операторы CASE и IIF?
Программа – это мысли спрессованные в код
Re[12]: и еще один вопрос по реляционной структуре
Здравствуйте, Qulac, Вы писали:
PD>>Вот только с UNION вопрос. Таблицы-то сильно разные. В них вообще может не быть одинаковых по смыслу полей, кроме ID, и то, если он в них есть(они могли бы использовать ID базовой как свой PK). Что брать-то ? И как потом определить, откуда взяли ?
Q>В чем проблема нужный запрос написать, sql поддерживает условные операторы CASE и IIF?
Да ради бога, а что брать-то и как определить, откуда взяли
В таблице группы есть одно поле number int. И FK на базовую
В таблице факультет есть одно поле name varchar. И FK на базовую, конечно
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Qulac, Вы писали:
PD>>>Вот только с UNION вопрос. Таблицы-то сильно разные. В них вообще может не быть одинаковых по смыслу полей, кроме ID, и то, если он в них есть(они могли бы использовать ID базовой как свой PK). Что брать-то ? И как потом определить, откуда взяли ?
Q>>В чем проблема нужный запрос написать, sql поддерживает условные операторы CASE и IIF?
PD>Да ради бога, а что брать-то и как определить, откуда взяли
PD>В таблице группы есть одно поле number int. И FK на базовую PD>В таблице факультет есть одно поле name varchar. И FK на базовую, конечно
PD>Что брать-то ?
Вот так например:
DECLARE @student_id INT = 2;
declare @faculty varchar(50);
declare @group varchar(50);
-- если у студента нету ссылки на факультет, то он зачислен в группу и все данные получаем по связи от группыif((select count(*) from students inner join students_sets on students.students_set_id=students_sets.students_set_id
inner join faculties on faculties.faculties_id=students_sets.students_set_id
where students.students_id = @student_id) = 0)
begin
set @group = (select groups.number
from students
inner join students_sets on students.students_set_id=students_sets.students_set_id
inner join groups on groups.groups_id = students_sets.students_set_id
where students.students_id=@student_id)
set @faculty = (select faculties.Name
from students inner join students_sets on students.students_id=students_sets.students_set_id
inner join groups on students.students_set_id=groups.groups_id
inner join faculties on faculties.faculties_id= groups.faculties_id
where students.students_id=@student_id)
end
else
begin
set @faculty = (select faculties.Name
from students inner join students_sets on students.students_id=students_sets.students_set_id
inner join faculties on faculties.faculties_id=students_sets.students_set_id
where students.students_id = @student_id);
end
select @faculty as 'Факультет', @group as 'группа'
Программа – это мысли спрессованные в код
Re[14]: и еще один вопрос по реляционной структуре
Здравствуйте, Qulac, Вы писали:
Q>Вот так например:
<skipped>
Ну не знаю. Может быть, это и будет работать, но нужно серьезное тестирование.
Вижу 2 таблицы : students и students_sets. Первая, полагаю, все студенты, а вторая что такое ?
И где тут базовая (в терминах предыдущих твоих постингов) таблица ? Или она и есть students_sets ?
В общем, рекомендовать это студентам я бы не стал. ИМХО слишком тяжелая артиллерия для , в общем-то, простой ситуации. В конце концов 2 FK от студента на группу и факультет хоть и не очень хорошо с точки зрения канонов, но терпимо.
Ну и концептуально мне это решение не нравится. Получается, что таблицы факультет и группа — братья и оба "потомки" от базовой. А по смыслу все же факультет : группа == parent:child. И не стоит ради того, чтобы решить локальную проблему, портить структуру .
А вот это решение вообще снимает все проблемы легко и изящно
Здравствуйте, m2user, Вы писали:
M>Виртуальная группа (одна на каждый факультет) в таблице `group` c FK на faculty. M>Помещать туда студентов без группы. M>В таблицу `group` добавить колонку с типом группы (обычная или имеет особый смысл).
Один недостаток у этого решения все же есть.
Курс , на котором студенты, достаточно поместить в `group`, так как вся группа на одном курсе.
Для этой виртуальной группы так не получится. Придется курс помещать в student, а там это лишнее, в общем-то. Для студентов внутри группы он не нужен.
Можно создать не одну, а 4 или 5 виртуальных групп, каждая по своему курсу. В этом даже какая-то логика есть — студенты, вышедшие из общего процесса на таком-то курсе. Если кто-то из них вернется даже через несколько лет — вся информация на месте. Вышел из общего процесса на 3 курсе, туда и надо вернуть. Так сказать, заморозка участия на неопределенный срок.
With best regards
Pavel Dvorkin
Re[15]: и еще один вопрос по реляционной структуре
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Qulac, Вы писали:
Q>>Вот так например:
PD><skipped>
PD>Ну не знаю. Может быть, это и будет работать, но нужно серьезное тестирование. PD>И где тут базовая (в терминах предыдущих твоих постингов) таблица ? Или она и есть students_sets ?
Да.
PD>В общем, рекомендовать это студентам я бы не стал. ИМХО слишком тяжелая артиллерия для , в общем-то, простой ситуации. В конце концов 2 FK от студента на группу и факультет хоть и не очень хорошо с точки зрения канонов, но терпимо.
Применять это на практике или нет — это уже другой вопрос, но способ есть для случаев когда у сущности могут быть взаимоисключающие связи с другими сущностями.
PD>Ну и концептуально мне это решение не нравится. Получается, что таблицы факультет и группа — братья и оба "потомки" от базовой. А по смыслу все же факультет : группа == parent:child. И не стоит ради того, чтобы решить локальную проблему, портить структуру .
Собственно это и есть наследование поведения — и факультет и группа могут содержать в себе студентов, т.е. у них есть общность.
PD>А вот это решение вообще снимает все проблемы легко и изящно
PD>https://rsdn.org/forum/db/8843919.1
Мое дело было предложить вариант решения. Вообще как известно используя реляционную модель можно смоделировать любую структуру данных в нормальной форме. Как это сделать в этом случае?
Q>Собственно это и есть наследование поведения — и факультет и группа могут содержать в себе студентов, т.е. у них есть общность.
Ну в общем-то да. В императивном языке явно напрашивается interface StudentHolder и Group и Faculty extends его.
А в то же время, если допустить, что только Group может иметь студентов, то Faculty может его и не имплементировать, что ничему не помешает, так как косвенно итерацией по группам мы все их получим.
Ну а если все же и сам Faculty может их иметь (то есть без виртуальной группы), то не скажу, что и это решение мне нравится.
Хотя...
Рассмотрим аналогичный пример. Товары в магазине в категориях (мясные, молочные, растительные...). Пусть каждый товар принадлежит только одной категории. Но есть товары, ни в одну категорию не входящие.
Тут возражений концептуальных нет.
А по сути то же самое.
Q>Мое дело было предложить вариант решения. Вообще как известно используя реляционную модель можно смоделировать любую структуру данных в нормальной форме. Как это сделать в этом случае?
Не знаю, я не большой специалист в теории БД и тем более в реляционной алгебре. Может, другие скажут ?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Пусть та же система, что и тут
Предлагаю подумать насчет хранения истории изменения принадлежности студента к группе.
Многие вопросы, даже еще не озвученные, снимутся.
Но, как обычно бывает, возникнут другие )))
PD>Можно создать не одну, а 4 или 5 виртуальных групп, каждая по своему курсу. В этом даже какая-то логика есть — студенты, вышедшие из общего процесса на таком-то курсе. Если кто-то из них вернется даже через несколько лет — вся информация на месте. Вышел из общего процесса на 3 курсе, туда и надо вернуть. Так сказать, заморозка участия на неопределенный срок.
Почему бы и нет — по одной виртуальной группе на каждый курс каждого факультета.
Кстати вариант с таблицами отношений (student-group, group-faculty) мне кажется более гибким, т.к. позволяет при необходимости поместить студента в несколько групп.
Но виртуальные группы там тоже будут нужны для связи студента без группы и факультета.
Здравствуйте, swimmers, Вы писали:
S>Предлагаю подумать насчет хранения истории изменения принадлежности студента к группе. S>Многие вопросы, даже еще не озвученные, снимутся.
Несомненно. Если вводить историю (версионность), то ее надо делать не только для принадлежности студента к группе, но и для самих групп.
Например, когда я учился, номер группы формировался так
код_факультета последняя_цифра_года_поступления номер_группы_в_этом году.
Поэтому, скажем, 822 группа — это и группа набора 1922 года, и 1932 года, ... 2022 года.
А еще после 3 курса все группы ликвидировали и распределили по новым группам в соответствии со специализацией
Были группы 821-823, а стали 821-825, при этом общего у прежней 822 и новой 822 ничего не было, хотя какие-то студенты и были до в 822 и оказались после в 822.
Ну а если дальше пойти — переименования, слияния и разделения факультетов...
Здравствуйте, m2user, Вы писали:
M>Кстати вариант с таблицами отношений (student-group, group-faculty) мне кажется более гибким, т.к. позволяет при необходимости поместить студента в несколько групп.
Для student-group вполне согласен. Более того, порой он единственно возможный, например, для спортшколы, где вполне реально, что кто-то входит в 2+ секции
Для group-faculty — сомневаюсь. Не могу представить группу, принадлежащую 2 факультетам одновременно.
Здравствуйте, paucity, Вы писали:
P>Ты бы начал с формализации требований/ТЗ/спецификаций (назови как хочешь) для твоей учебной задачи -- основные моменты без растекания.
P>Например, если в требованиях будет зафиксированно, что студент может быть только в одной группе и историю переводов из группы в группу, или с факультета на факультет хранить не надо, то и вопросов меньше.
Да, ты прав, я как-то не подумал. Надо было с самого начала объяснить, что это модельная учебная задача, а вовсе не для production.
Исправляюсь.
В общем, есть у меня учебное упражнение по основам SQL а потом MyBatis и Hibernate.
Задача простая — факультет, группы, студенты, предметы
Цель — освоить SQL и остальное. PK, FK, WHERE всякие, JOIN и т.п. В общем, основы SQL , начальный курс. Без триггеров и SP.
Ну и many :1 (student : group) и many:many (group:subject).
Институт я в этой модели опустил. Лес факультетов с группами и студентами в них. Естественно, только текущее состояние, никакой истории.
А с другой стороны, правила тут должны быть именно те, что в реальности. Предметная область студентам очень уж хорошо знакома
И вот я подумал, не расширить ли задачу, добавив институт. В исходной задаче принадлежность студентов замалчивается. Они члены групп или не члены, а те, что не члены, явно ни чему не принадлежат.
Ну и возникли 2 вопроса. Первый — про единственную запись в таблице институт, а вторая — к чему принадлежат студенты, не входящие в группы.
Здравствуйте, sergeya, Вы писали:
S>Закон разрешает студентам одновременно осваивать несколько образовательных программ.
Да, верно, я как-то забыл об этом.
Лет 25 назад был у меня один студент, мой курсовик. Доучился до 3 курса, а потом сообщил мне, что он поступил еще на заочное на юрфак.
Я ему сказал, что не получится у него, времени не хватит. Он ответил, что хватит.
Через полгода мы встретились, и он сказал : "Вы были правы". Пришел он забрать документы.
Больше я его не видел.
PD>пусть есть таблица institute с одной строкой. Или как-то иначе. Это здесь не обсуждаем.
PD>Есть факультеты. Таблица faculty с FK (или без него, как хотите) на institute
PD>На факультете есть группы. Таблица `group` с FK на faculty.
PD>А еще есть студенты. Таблица student и вот тут вопрос
Один и тот же человек может одновременно учиться на разных факультетах. Дневной + заочка. Или на одном, но на разных специальностях.
Поэтому связь студента с факультетом и группой через промежуточную таблицу. Там связь M:N.
Да каждый человек имеет сслылку на хотя бы 1 факультет (обязательно). И возможно на группу, а если в академе, то не имеет ссылки на группу, только на факультет.
И еще нужно разрулить когда он на одно и том же факультете учится на одной специальности, а на 2 а академе.
Нужен отдельной таблице список студентов в академе получается.
Итого
Факультеты
Группы
Академы
Студенты.
И таблицы для связей всего этого. Как-то так.
Здравствуйте, Pavel Dvorkin, Вы писали: PD>На императивном языке можно было бы ограничиться одной ссылкой на некий интерфейс или базовый класс. Если студент член группы, то на Group (а она на Faculty), если не член — прямо на Faculty. Может, и не лучшее решение, но возможное. А тут одним FK можно обойтись ?
Одним — нет, нельзя. Но можно получить гарантию непротиворечивости.
Первый FK — композитный, Student(GroupID, FacultyID) -> Group(ID, FacultyID)
Второй FK — простой, Student(FacultyID) -> Faculty(ID)
Первый предотвращает возможность попасть в группу с чужого факультета. Второй предотвращает возможность попасть на несуществующий факультет при пустой группе. https://www.db-fiddle.com/f/4m6HA2zSzdKCE4bKSVwEtu/0
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Одним — нет, нельзя. Но можно получить гарантию непротиворечивости. S>Первый FK — композитный, Student(GroupID, FacultyID) -> Group(ID, FacultyID) S>Второй FK — простой, Student(FacultyID) -> Faculty(ID) S>Первый предотвращает возможность попасть в группу с чужого факультета. Второй предотвращает возможность попасть на несуществующий факультет при пустой группе.
То есть когда студент становится студентом вне группы, Student.GroupID ставится в NULL ? А что тогда получится с первым FK ?
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>То есть когда студент становится студентом вне группы, Student.GroupID ставится в NULL ? А что тогда получится с первым FK ? S>Ничего особенного. Если один из компонентов FK null, то он не проверяется. S>Я же дал ссылку — нажмите на неё.
Ссылка у меня что-то не открывается. Точнее, заголовок появляется и все.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Есть факультеты. Таблица faculty с FK (или без него, как хотите) на institute PD>На факультете есть группы. Таблица `group` с FK на faculty. PD>А еще есть студенты. Таблица student и вот тут вопрос PD>Студент входит в группу, но ей не принадлежит. После приказа ректора о зачислении он на короткое время становится студентом вне группы, пока его в группу декан не определит. Если уйдет в академотпуск, то до возвращения из него будет опять студентом вне группы.
… PD>В итоге у студента должно быть 2 FK — на группу и факультет. Но группа имеет FK на факультет. Получается, что студент фактически имеет 2 FK на факультет — один явно, а другой косвенно, через свой FK на группу и FK группы на факультет.
Как вариант: иметь у студента и ссылку на факультет и ссылку на группу, обе NULL-абельные и CHECK constraint что только одна из них может иметь значение и хотя бы одна из них должна иметь значение.
Как будет лучше, или так или с помощью "специальной" группы, как предложили выше, можно понять с помощью запросов, которые нужно будет составлять.
Help will always be given at Hogwarts to those who ask for it.