Мы пишем продукт для управления записями для школ, и одним из требований является способность управлять расписаниями курсов. Я не смотрел код, как мы справляемся с этим (сейчас я нахожусь в другом проекте), но тем не менее я начал задаваться вопросом, как лучше всего справиться с одной частью этого требования, а именно, как справиться с тем, что каждый курс может проводиться один или несколько дней недели и как лучше всего хранить эту информацию в базе данных. Чтобы обеспечить некоторый контекст, таблица bare-bones Course
может содержать следующие столбцы:
Course Example Data
------ ------------
DeptPrefix ;MATH, ENG, CS, ...
Number ;101, 300, 450, ...
Title ;Algebra, Shakespeare, Advanced Data Structures, ...
Description ;...
DaysOfWeek ;Monday, Tuesday-Thursday, ...
StartTime
EndTime
Что мне интересно, каков наилучший способ обработки столбца DaysOfWeek
в этом (надуманном) примере? Проблема, с которой я сталкиваюсь, заключается в том, что это многозначное поле: то есть вы можете иметь курс в любой день недели, и один и тот же курс может проводиться более одного дня. Я знаю, что определенные базы данных изначально поддерживают многозначные столбцы, но есть ли "лучшая практика" для этого, предполагая, что база данных не поддерживает ее?
Я до сих пор предлагал следующие возможные решения, но мне интересно, есть ли у кого-нибудь лучшее:
Возможное решение №1: Обработать DaysOfWeek как поле бит
Это первое, что появилось в моей голове (я не уверен, что это хорошо или нет...). В этом решении DaysOfWeek
будет определяться как байт, а первые 7 бит будут использоваться для представления дней недели (по одному бит для каждого дня). 1 бит означает, что класс был проведен в соответствующий день недели.
Преимущества: легко реализуется (приложение может работать с манипуляциями с битами), работает с любой базой данных.
Минусы: сложнее писать запросы, которые используют столбец DaysOfWeek
(хотя вы можете справиться с этим на уровне приложения или создать представления и хранимые процедуры в базе данных, чтобы упростить это), breaks реляционной базы данных.
Возможное решение # 2: сохранить DaysOfWeek в виде строки символов
Это по существу тот же подход, что и использование битового поля, но вместо обращения к необработанным битам вы назначаете уникальное письмо для каждого дня недели, а столбец DaysOfWeek
просто хранит последовательность букв, указывающую, какие дни курс проводится. Например, вы можете связать каждый день недели с одним символьным кодом следующим образом:
Weekday Letter
------- ------
Sunday S
Monday M
Tuesday T
Wednesday W
Thursday R
Friday F
Saturday U
В этом случае курс, проводимый в понедельник, вторник и пятницу, будет иметь значение 'MTF'
для DaysOfWeek
, а класс, который будет проводиться только по средам, будет иметь значение DaysOfWeek
'W'
.
Преимущества: проще справиться с запросами (т.е. вы можете использовать INSTR
или его эквивалент, чтобы определить, удерживается ли класс в данный день). Работает с любой базой данных, которая поддерживает INSTR или эквивалентную функцию (большинство, я бы предположил...). Также более дружелюбно смотреть и легко видеть, что происходит в запросах, которые используют столбец DaysOfWeek
.
Против. Единственный реальный "кон" - это то, что, подобно подходу битового поля, это разбивает реляционную модель, сохраняя переменное число значений в одном поле.
Возможное решение №3: используйте таблицу поиска (уродливый)
Еще одна возможность - создать новую таблицу, в которой хранятся все уникальные комбинации дней недели, и столбец Course.DaysOfWeek
просто будет внешним ключом в этой таблице поиска. Тем не менее, это решение кажется самым неэлегантным, и я только рассматривал его, потому что это делалось так, как это делалось в Relational Way TM.
Преимущества: это единственное решение, которое является "чистым" с точки зрения реляционной базы данных.
Против: он неэлегантный и громоздкий. Например, как бы вы создали пользовательский интерфейс для назначения соответствующих будних дней данному курсу вокруг таблицы поиска? Я сомневаюсь, что пользователь хочет иметь дело с выборами по строкам "воскресенье", "воскресенье, понедельник", "воскресенье, понедельник, вторник", "воскресенье, понедельник, вторник, среда" и т.д....
Другие идеи?
Итак, есть ли более элегантный способ обработки нескольких значений в одном столбце? Или один из предложенных решений будет достаточным? Для чего это стоит, я думаю, что мое второе решение, вероятно, является лучшим из трех возможных решений, которые я изложил здесь, но мне было бы интересно узнать, есть ли у кого-то другое мнение (или вообще совсем другой подход).