mysql - It is ok to have n amount of columns? - mysql

I know it's possible to have n amount of columns, but is it proper mysql "coding standard"?
Here is what I'm doing:
I am a table student which includes all the students info including testScores:
student
-------
studId
name
age
gender
testId
Instead of putting each individual test answer within the student table, I made a separate table called testAnswers that will hold each students test results:
testAnswers
-----------
testId
ques1
ques2
.
.
.
quesN
Each entry in the testAnswers table corresponds to a specific student in the table student.
Of course, there will be an admin that will be able to add questions and remove questions as each year the test questions may change. So, if the admin were to remove an answer, than that means one of the columns would be removed.
Just to reiterate myself, I know this is possible to edit and remove columns in a table in mysql, but is good "coding standard"?

The answer is a simple and clear: No. That's just not how you should do it except for very few corner cases.
The usual way to approach this is to normalize your database. Normalization follows a standard procedure that (among other things) avoids having a table with columns names ques1, ques2, ques3 ....
This process will lead you to a database with three tables:
students - id, name, and other stuff that applies to one student each
questions - id and question text for each question
answers - this is a N:M relation between students: student_id, question_id, answer_value

Use two tables!
What you are describing is a one to many relationship as there can be one student to many test scores. You would need to have some id as a foreign key to the student_id and put this id in the testAnswers table. You can then set constraints, which tell the database how to handle removal of data.
As one commenter has mentioned, using one table would result in breaking 1nf or first normal form which basically says that you cannot have multiple values for a single column given a particular record - You can't have multiple test scores for the same user in a given table, instead break the data up into two tables.

...of course 2 tables, also could use 3, just remember to insert a studId column also in the testAnswers table (with REFERENCE to the student table) and an INNER JOIN testAnswers ON student.studId=testAnswers.studId at the SELECT query (to read the data).

Related

mysql DB management - hours for each student

I am going to write some code to retrieve and add to/remove from a student's hours that they have signed up for. For example...
student 1:
October 20th:
12am
4pm
7pm
October 21st:
8pm
student 2
October 19th
1pm
6pm
I'm trying to wrap my head around how to create this type of table setup on phpmyadmin with each student having a dynamic number of hours, and different times, and different days. I am new to mysql management, am vaguely familiar with joins and stuff, and am just now starting to expand my database to more complex things like this. What I have learned so far is that enums is NOT where I want to go. Just unsure of a starting point...
What is a good strategy for doing something like this?
Thank you,
you need to create many to many relation
first i try to explain it simple and fast:
1- you need to make a table for hours, each hours have 1 row.
2- i guess you already have a student table
3- now you need a table that contain only 2 column, first column is hours table id, second column is student id.
at the end you simply need to execute select command like this:
select * from StudentHours Table where student-id = 1;
Detailed Information:
Relational database systems usually don't allow you to implement a direct many-to-many relationship between two tables. Consider the example of keeping track of invoices. If there were many invoices with the same invoice number and one of your customers inquired about that invoice number, you wouldn't know which number they were referring to. This is one reason for assigning a unique value to each invoice.
To avoid this problem, you can break the many-to-many relationship into two one-to-many relationships by using a third table, called a join table. Each record in a join table includes a match field that contains the value of the primary keys of the two tables it joins. (In the join table, these match fields are foreign keys.) These foreign key fields are populated with data as records in the join table are created from either table it joins.
A typical example of a many-to many relationship is one between students and classes. A student can register for many classes, and a class can include many students.
The following example includes a Students table, which contains a record for each student, and a Classes table, which contains a record for each class. A join table, Enrollments, creates two one-to-many relationships—one between each of the two tables.

Prevent duplicated ID on MySQL (InnoDB) across 2 tables

Is it possible to have the ID of the next generated row (across 2 tables) be unique?
I have 4 tables:
1 for teachers
1 for students
1 for projects
1 for relations
The relations table has 3 foreign keys.
One refers to teachers IDs, one to students IDs and the other to projects IDs
Since a project can be related to teachers but also students at the same time, how do I make sure that a new created teacher or student won't have an ID already used by the other type of account?
If I can do that, then the relations table would have only 3 columns:
ID, project_ID and related_to(ID)
If not, I would have to add a 4th row indicating the type of account that it relates to (student or teacher).
Thanks for your help!
Regarding the difference between account types:
I have to translate this exact same situation to another project of mine in which the first two tables are completely different. That's why I don't bother to merge the students and teachers tables here.
You do not need to have unique values between the student and teacher tables because the relation table has separate fields for each relationship, so there is no conflict.
However, this is not the right way to do things. You need two relation tables, teacher_project and student_project. Alternatively, depending on the unique data that's different between teachers and students, you could have a single person table and a single relationship, which is probably closer to the real world anyway.
I think you can identify the teachers begin with 1 ,incremental 2; the students begin with 2 ,incremental 2.By this way,odd number refers to teacher while even number refers to student.No conflict will happen.

Little Database Performance Puzzle

I am not really experienced with databases but I have a little problem. I am trying to create a database that stores the courses being taken by students and lecturers so I created three tables. In the lecturer and student tables, the field courses represent a comma separated list of the courses taken by either the lecturer or the student.
Something like this:
Lecturer - Courses - "1,2"
Student - Courses - "1,2,3"
Courses - 1 - "Bio"
The problem however is that when I want to show a list of student based on their courses, I have to search all the students and the courses and search again to check whether the csv list has the specified course (which seems a bit redundant). Is there another way I can achieve this goal, say by relating/referencing the indexes or something? Thanks
Create two new tables:
student_courses(int student_id, int course_id)
lecturer_courses(int lecturer_id, int course_id)
You can now create individual rows for each course a student is taking and each course a lecturer is teaching, assuming that you want to track delivery of a course separate from taking the course. You can then write queries against those tables using course id when you want to do course related analysis.
the field courses represent a comma separated list of the courses taken by either the lecturer or the student
A field that contains a csv list is breaking First Normal Form (1NF) and has all sorts of problems, including performance. Breaking out this field into a separate Junction Table {StudentID, CourseID} is what you should do.
Instead of storing a text like "1,2,3", store several rows:
1 row for every student in a table named "students"
1 row for every course in a table named "courses"
Then create another table named "student_in_course" which has 1 row for every combination.
Then do the same for "lecturer_in_course".

Mysql table layout with multiple values for same column

I am integrating a friends system for my website...
One question I have about the mysql table is how it is to be set up.
Will I have many columns for each friend they add, such as freind 1, 2, 3, 4, 5 and so on and the row will be the user who has added them.
Is there a better way to do this?? With my first thought doing it that way would mean a cap on the amount of friends someone can have...
Your suggestion of multiple columns would violate first normal form. As well as artificially restricting the number of friends such structures are tedious to work with and inefficient.
You need a junction table for friends with 2 columns (userid1,userid2) that form a composite primary key. Both columns would have a FK relationship with the user table.
In many RDBMSs you would also have a check constraint userid1 > userid2 so a relationship can only be stored in one form but I believe check constraints are somewhat broken in MySQL.
You will need an additional table with records for each friend a member has. For example:
members (id, name)
friends (member1, member2)

MySQL: LIKE Query Help?

I have a column in my table called student_id, and I am storing the student IDs associated with a particular record in that column, delimited with a | character. Here are a couple sample entries of the data in that column:
243|244|245
245|1013|289|1012
549|1097|1098|245|1099
I need to write a SQL query that will return records that have a student_id of `245. Any help will be greatly appreciated.
Don't store multiple values in the student_id field, as having exactly one value for each row and column intersection is a requirement of First Normal Form. This is a Good Thing for many reasons, but an obvious one is that it resolves having to deal with cases like having a student_id of "1245".
Instead, it would be much better to have a separate table for storing the student IDs associated with the records in this table. For example (you'd want to add proper constraints to this table definition as well),
CREATE TABLE mytable_student_id (
mytable_id INTEGER,
student_id INTEGER
);
And then you could query using a join:
SELECT * FROM mytable JOIN mytable_student_id
ON (mytable.id=mytable_student_id.mytable_id) WHERE mytable_student_id.student_id = 245
Note that since you didn't post any schema details regarding your original table other than that it contains a student_id field, I'm calling it mytable for the purpose of this example (and assuming it has a primary key field called id -- having a primary key is another requirement of 1NF).
#Donut is totally right about First Normal Form: if you have a one-to-many relation you should use a separate table, other solutions lead to ad-hoccery and unmaintainable code.
But if you're faced with data that are in fact stored like that, one common way of doing it is this:
WHERE CONCAT('|',student_id,'|') LIKE '%|245|%'
Again, I agree with Donut, but this is the proper query to use if you can't do anything about the data for now.
WHERE student_id like '%|245|%' or student_id like '%|245' or student_id like '245|%'
This takes care of 245 being at the start, middle or end of the string. But if you aren't stuck with this design, please, please do what Donut recommends.