2009-04-08 4 views
5

Je crée une base de données Access à utiliser dans une application C# à l'école. Je n'ai pas beaucoup d'expérience de travail avec DB, donc si cela semble stupide, ignorez-le. Je veux que l'utilisateur puisse sélectionner tous les classes qu'un certain étudiant a eu dans notre département informatique. Nous avons environ 30 au total et le maximum qu'une personne peut prendre en 4 années de lycée est 15. En ce moment ma DB a 15 colonnes différentes pour chaque classe qu'un utilisateur pourrait avoir. Comment puis-je compresser cela en une colonne (s'il y a un moyen)?Comment se débarrasser de plusieurs colonnes dans une base de données?

Répondre

18

excellente question Lucas, et ce plonge dans l'acte de la normalisation de la base de données.

Le fait que vous ayez reconnu pourquoi avoir plusieurs colonnes pour représenter des classes est déjà mauvais montre déjà que vous avez un grand potentiel.

Et si nous voulions ajouter une nouvelle classe? Maintenant, nous devons ajouter une toute nouvelle colonne. Il y a peu de flexibilité pour cela.

Alors, que peut-on faire?

Nous créons TROIS tables.

Une table est pour les étudiants:

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

Une table est pour les classes:

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

Et enfin, une table détient la relation entre les étudiants et les classes:

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

Si nous voulions inscrire John dans la physique, nous insérerions une ligne dans la table Student_Class. Maintenant, nous avons un record disant que l'étudiant # 1 (John) suit la classe # 2 (Physique). Faisons en sorte que Sally assiste à Maths, et Stan à la physique et aux mathématiques.

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); 

Pour tirer ces données en arrière de façon lisible, nous rejoignons les trois tables ensemble:

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

Cela nous donnerait un jeu de résultats comme celui-ci:

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

Et est comment la normalisation de la base de données fonctionne en un mot.

+0

Excellente réponse. En plus de l'information (précieuse, correcte) donnée, j'ajouterais que vous pouvez stocker des données supplémentaires sur les classes prises. Si vous utilisez DB pour l'Org, il sera amélioré dans les années suivantes. Cette conception permet cela. Classe d'année prise, tuteur, résultat, etc. peuvent être ajoutés. – Karl

+0

Merci pour le compliment mais honnêtement, je ne pouvais pas supporter le défilement horiszontally à travers 15 classes. Votre réponse a vraiment aidé et maintenant j'ai commencé à lire sur la normalisation.Je pense qu'avec l'aide de votre conception, je serai en mesure de faire une application décente pour mon professeur (elle va réellement l'utiliser). – Kredns

1

Que diriez-vous des colonnes de classe non dans la table d'étudiant. Configurez une nouvelle table avec les colonnes ID étudiant et ID de classe. Chaque rangée représente une classe que l'élève a suivie. Peut-être ajouter plus de colonnes telles que: l'année/semestre, année, etc.

+0

Pouvez-vous expliquer un peu plus, je ne suis pas exactement. – Kredns

4

On dirait que vous devez penser à votre normalizing schéma de base de données.

Il existe un many-to-many relationship entre les étudiants et les classes, de sorte que de nombreux étudiants peuvent suivre plusieurs cours et de nombreux cours peuvent être suivis par de nombreux étudiants. L'approche la plus courante pour gérer ce scénario consiste à utiliser un junction table.

Quelque chose comme ça

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

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

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

Vos requêtes se joindraient sur les tables, par exemple,

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 

Un conseil que je voudrais mentionner est que l'accès vous oblige à utiliser entre parenthèses lorsque En rejoignant plus de table dans une requête, je crois que c'est parce que cela nécessite de spécifier un ordre dans lequel les rejoindre. Personnellement, je trouve cela bizarre, surtout quand je suis habitué à écrire beaucoup de SQL sans concepteur. Dans Access, je recommanderais d'utiliser le concepteur pour joindre des tables, puis de modifier le code SQL généré pour vos besoins.

4

Vous avez donc 15 colonnes (par exemple class1, class2, class3 ... class15)?

On dirait que vous avez un classique many-to-many relationship. Vous devriez créer une nouvelle table pour relier les étudiants et les classes.

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

Si vous cours le suivi sur une base annuelle par année, vous pouvez ajouter une colonne année à la relation ainsi:

student_classes { StudentID, Year, ClassID } 
2

Il s'agit d'un problème de normalisation. En effet, vous posez la mauvaise question. Au lieu de vous poser la question comment pouvez-vous stocker 0 ou plus classes_taken? Quels autres détails avez-vous besoin de stocker à propos de chaque cours pris? Par exemple. juste la classe prise, ou les données prises, résultat, etc?

Par exemple, considérons somethin comme suit

 
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) 
... 

2

Vous ne devriez jamais avoir des colonnes comme Class1, class2, class3, class4 etc dans une table de base de données. Ce que vous devriez avoir est une table liée. Votre stucture serait quelque chose comme:

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

Puis

Course table with the following columns 
CourseId 
CourseName 

Puis

StudentCourse Table with the following columns 
StudentId 
CourseID 
CourseDate 

Maintenant, pour savoir quels cours la personne a pris vous joindre à ces tables ensemble. Quelque chose comme:

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

S'il vous plaît lire ce lien pour commencer l'apprentissage des fondamentaux de base de données: http://www.deeptraining.com/litwin/dbdesign/FundamentalsOfRelationalDatabaseDesign.aspx

+0

Je ... envoie le drapeau si vous avez plus d'une colonne pointant vers le même FK * et * cette colonne a un numéro suivant le nom. – dotjoe

Questions connexes