2009-04-08 10 views
5

Estoy creando una base de datos de acceso para su uso en una aplicación C# en la escuela. No he tenido mucha experiencia trabajando con DB así que si esto suena estúpido solo ignóralo. Quiero que el usuario pueda seleccionar todas las las clases que un determinado alumno ha tenido en nuestro departamento de TI. Tenemos alrededor de 30 en total y el máximo que una persona puede tomar en 4 años de escuela secundaria es 15. En este momento mi base de datos tiene 15 columnas diferentes para cada clase que un usuario podría tener. ¿Cómo puedo comprimir esto en una columna (si hay una forma)?¿Cómo deshacerse de múltiples columnas en una base de datos?

Respuesta

18

excelente pregunta Lucas, y esto se adentra en el acto de la normalización de la base de datos.

El hecho de que hayas reconocido por qué tener varias columnas para representar clases es malo, ya muestra que tienes un gran potencial.

¿Qué pasa si queremos agregar una nueva clase? Ahora tenemos que agregar una columna completamente nueva. Hay poca flexibilidad para esto.

Entonces, ¿qué se puede hacer?

Creamos TRES tablas.

Una tabla es para los estudiantes:

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

Una tabla es para Clases:

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

Y, por último, una mesa sostiene la relación entre los estudiantes y las clases:

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

Si quisiéramos inscribir a John en Física, insertaríamos una fila en la tabla Student_Class.

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

Ahora, tenemos un registro que dice que el Estudiante # 1 (John) asiste a la Clase # 2 (Física). Hagamos que Sally asista a Matemáticas y Stan asista a Física y Matemáticas.

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

Para sacar esos datos de forma legible, nos sumamos a las tres mesas:

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

Esto nos daría un conjunto de resultados como esto:

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

Y eso es cómo funciona la normalización de bases de datos en pocas palabras.

+0

Excelente respuesta. Además de la información (valiosa, correcta) proporcionada, agregaría que puede almacenar datos adicionales sobre las clases tomadas. Si DB es útil para Org, se mejorará en años posteriores. Este diseño permite eso. Se puede agregar la clase de año tomada, tutor, resultado, etc. – Karl

+0

Gracias por el cumplido, pero sinceramente, no podía soportar desplazarse horizontalmente a través de 15 clases. Su respuesta realmente ayudó y ahora comencé a leer sobre la normilización.Creo que con la ayuda de tu diseño podré hacer una aplicación decente para mi maestra (en realidad la va a usar). – Kredns

1

¿Qué tal si no hay columnas de clase en la tabla de alumnos? Configure una nueva tabla con las columnas de id. De clase y identificación de clase. Cada fila representa una clase que el alumno tomó. Tal vez agregue más columnas como: el año/semestre, grado, etc.

+0

Puede explicar esto un poco más, no sigo exactamente. – Kredns

4

Parece que necesita pensar en normalizing el esquema de su base de datos.

Hay un many-to-many relationship entre estudiantes y clases, de modo que muchos estudiantes pueden tomar muchas clases y muchos estudiantes pueden tomar muchas clases. El enfoque más común para manejar este escenario es usar un junction table.

Algo como esto

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

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

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

Entonces las consultas se unirían en las mesas, por ejemplo,

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 consejo que me gustaría mencionar es que el acceso requiere el uso de paréntesis cuando Al unir más de una tabla en una consulta, creo que es porque requiere que especifiques un orden en el que unirlos. Personalmente, encuentro esto incómodo, particularmente cuando estoy acostumbrado a escribir mucho SQL sin diseñadores. Dentro de Access, recomendaría usar el diseñador para unir tablas, luego modificar el SQL generado para sus propósitos.

4

¿Tienes 15 columnas (por ejemplo, class1, class2, class3 ... class15)?

Parece que tiene un clásico many-to-many relationship. Debe crear una nueva tabla para relacionar estudiantes y clases.

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

Si está rastreando clases sobre una base año tras año, se podría añadir una columna de año a la relación, así:

student_classes { StudentID, Year, ClassID } 
2

Este es un problema de normalización. En efecto, estás haciendo la pregunta incorrecta. En lugar de eso, hágase la pregunta ¿cómo puede almacenar 0 o más clases_taken? ¿Qué otros detalles necesita almacenar sobre cada clase tomada? P.ej. solo la clase tomada, o los datos tomados, el resultado, etc.?

Por ejemplo considerar algo como lo siguiente

 
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

Nunca se debe tener columnas como clase 1, clase 2, clase 3, class4 etc en una tabla de base de datos. Lo que debes tener es una tabla relacionada. Su stucture sería algo así como:

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

Entonces

Course table with the following columns 
CourseId 
CourseName 

Entonces

StudentCourse Table with the following columns 
StudentId 
CourseID 
CourseDate 

ahora para saber qué cursos se llevó a la persona se une a estas tablas juntos. Algo así como:

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

Por favor, lea este enlace para empezar a aprender los fundamentos de bases de datos: http://www.deeptraining.com/litwin/dbdesign/FundamentalsOfRelationalDatabaseDesign.aspx

+0

I aqree ... arroje la bandera si alguna vez tiene más de una columna apuntando al mismo FK * y * esa columna tiene un número que sigue al nombre. – dotjoe

Cuestiones relacionadas