Как избавиться от нескольких столбцов в базе данных? - PullRequest
5 голосов
/ 09 апреля 2009

Я создаю Access DB для использования в приложении на C # в школе. У меня не было большого опыта работы с БД, так что если это звучит глупо, просто игнорируйте это. Я хочу, чтобы пользователь мог выбрать все классы, которые у определенного студента были в нашем отделе ИТ. У нас их около 30, и максимум, что человек может взять за 4 года старшей школы, составляет 15. Прямо сейчас моя БД имеет 15 различных столбцов для каждого класса, который может иметь пользователь. Как я могу сжать это до одного столбца (если есть способ)?

Ответы [ 6 ]

18 голосов
/ 09 апреля 2009

Отличный вопрос, Лукас, и это углубляется в процесс нормализации базы данных.

Тот факт, что вы поняли, почему иметь несколько столбцов для представления классов - это плохо, уже показывает, что у вас большой потенциал.

Что, если мы хотим добавить новый класс? Теперь мы должны добавить совершенно новый столбец. Для этого мало гибкости.

Так что же можно сделать?

Мы создаем ТРИ таблицы.

Один стол для студентов:

Student
   |-------------------------|
   | StudentID | Student_Name|
   |-------------------------|
   |     1     |     John    |
   |     2     |     Sally   | 
   |     3     |     Stan    | 
   ---------------------------

Один стол предназначен для занятий:

Class
   ------------------------
   | ClassID  | Class_Name|
   ------------------------
   |    1     |   Math    |
   |    2     |   Physics |
   ------------------------

И, наконец, одна таблица содержит отношения между учениками и классами:

Student_Class
   -----------------------
   | StudentID | ClassID |
   -----------------------

Если бы мы хотели записать Джона в физику, мы вставили бы строку в таблицу Student_Class.

  INSERT INTO Student_Class (StudentID, ClassID) VALUES (1, 2);

Теперь у нас есть запись о том, что студент № 1 (Джон) посещает урок № 2 (физика). Пусть Салли посещает математику, а Стэн - физику и математику.

  INSERT INTO Student_Class (StudentID, ClassID) VALUES (2, 1);
  INSERT INTO Student_Class (StudentID, ClassID) VALUES (3, 1);
  INSERT INTO Student_Class (StudentID, ClassID) VALUES (3, 2);

Чтобы получить эти данные обратно в удобочитаемом виде, мы объединяем три таблицы:

  SELECT Student.Student_Name, 
         Class.Class_Name 
  FROM Student, 
       Class, 
       Student_Class 
  WHERE Student.StudentID = Student_Class.StudentID 
       AND Class.ClassID = Student_Class.ClassID;

Это даст нам набор результатов, подобный этому:

  ------------------------------
  | Student_Name  | Class_Name |
  ------------------------------
  |    John       |  Physics   |
  |    Sally      |   Math     |
  |    Stan       |  Physics   |
  |    Stan       |   Math     |
  ------------------------------

И вот как нормализация базы данных работает в двух словах.

4 голосов
/ 09 апреля 2009

Итак, у вас есть 15 столбцов (например, class1, class2, class3 ... class15)?

Похоже, у вас классические отношения ко многим . Вы должны создать новую таблицу, чтобы связать учащихся и классы.

student { StudentID, StudentName ... }
classes { ClassID, ClassName ... }
student_classes { StudentID, ClassID }

Если вы отслеживаете классы на годичной основе, вы также можете добавить столбец года к взаимосвязи:

student_classes { StudentID, Year, ClassID }
4 голосов
/ 09 апреля 2009

Похоже, вам нужно подумать о нормализации вашей схемы базы данных.

Существует отношение «многие ко многим» между учащимися и классами, так что многие учащиеся могут посещать много классов, а многие учащиеся могут посещать многие занятия. Наиболее распространенный подход к обработке этого сценария заключается в использовании таблицы соединений .

как то так

Student Table
-------------
id
first_name
last_name
dob

Class Table
-----------
id
class_name
academic_year

Student_Class Table
-------------------
student_id
class_id
year_taken

Тогда ваши запросы будут объединяться в таблицах, например,

SELECT
    s.last_name + ', ' + s.first_name AS student_name,
    c.class_name,
    sc.year_taken
FROM
    student s
INNER JOIN
    student_class sc
ON
    s.id = sc.student_id
INNER JOIN
    class c
ON
    sc.class_id = class.id
ORDER BY
    s.last_name, sc.year_taken

Один совет, который я хотел бы упомянуть, заключается в том, что Access требует от вас использовать круглые скобки при соединении в запросе не только таблицы, я полагаю, что это потому, что вам требуется указать порядок, в котором они должны быть присоединены. Лично я нахожу это неловким, особенно когда я привык писать много SQL без дизайнеров. В Access я бы рекомендовал использовать конструктор для объединения таблиц, а затем изменить сгенерированный SQL для ваших целей.

2 голосов
/ 09 апреля 2009

У вас никогда не должно быть столбцов, таких как class1, class2, class3, class4 и т. Д. В таблице базы данных. То, что вы должны иметь, это связанная таблица. Ваша структура была бы что-то вроде:

Student Table with the following columns
StudentID
StudentLastName
StudentFirstName 
(and so forth for all the data to describe a student)

Тогда

Course table with the following columns
CourseId
CourseName

Тогда

StudentCourse Table with the following columns
StudentId
CourseID
CourseDate

Теперь, чтобы узнать, какие курсы посещал человек, вы присоединитесь к этим столам вместе. Что-то вроде:

Select StudentID,StudentLastName,StudentFirstName, CourseName, CourseDate
from Student 
join StudentCourse on student. studentid = StudentCourse.StudentID
join Course on Course.courseID = StudentCourse.CourseID 

Пожалуйста, прочитайте эту ссылку, чтобы начать изучение основ базы данных: http://www.deeptraining.com/litwin/dbdesign/FundamentalsOfRelationalDatabaseDesign.aspx

2 голосов
/ 09 апреля 2009

Это проблема нормализации. По сути, вы задаете не тот вопрос. Вместо этого задайте себе вопрос, как вы можете хранить 0 или более classes_taken? Какие еще детали нужно хранить о каждом взятом уроке? Например. только взятый класс или полученные данные, результат и т. д.

Например, рассмотрим что-то вроде следующего

table Student
 id int
 name varchar(25)
 ...

table classes
 id int
 name varchar(25)
 ...

table clases_taken
 student_id int (foreign key to student.id)
 class_id int (foreign key to class.id)
 data_started datatime
 result varchar(5)
 tutor_id int (foreign key to tutor.id)
 ...

1 голос
/ 09 апреля 2009

Как насчет отсутствия столбцов классов в таблице учеников. Настройте новую таблицу со столбцами идентификатора студента и идентификатора класса. Каждый ряд представляет класс, который взял студент. Возможно, добавьте больше столбцов, таких как: год / семестр, класс и т. Д.

...