Mysql table layout with multiple values for same column - mysql

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)

Related

Establishing relationships in a database between multiple tables

I have a web application which allows users to join multiple groups.
I have a 'users' table which stores details about the users (id, email, password, etc.) and a 'groups' table which stores details about the available groups (id, name, owner of group).
I have been researching the best way to store group memberships (i.e. which users are in which group, bearing in mind they can be members of multiple) - however I am still not sure what the most efficient solution would be.
Would you recommend I:-
Create a second table called 'group_memberships' and store the user's ID along with the corresponding group ID?
Store an array alongside the group particulars in the 'groups' table with the user IDs of its members?
Approach this task a different way?
The DBMS I am using is phpMyAdmin.
I would advise you to go with option 1; where you have a Mapping Table for linking Users & Groups.
The Users Table will have PK on User_ID.
The Groups table will have PK on Group_ID.
The Mapping table will have User_ID(FK) and Group_ID(FK).
Now you should have PK on these two columns together.
This will ensure you don't have duplicate entries.
What you're describing is called a many-to-many relationship in database terms. A user can belong to multiple groups, and groups have more than one user (or else they wouldn't be "groups"!).
Your first idea, the group_memberships table, is the accepted best way to model this relationship. Although you'll want to name it users_groups or something similar to reflect the fact it relates or associates those two tables. At its most basic, this association table needs three columns:
ID (primary key)
user_id (foreign key)
group_id (foreign key)
By JOINing to this table ON either user_id or group_id, you can find the related records from either side of the relationship. And you can do it right from a SQL query, without any additional code like you'd need if you stored an array.
I would definitely go with option 1 - creating the junction table 'group_memberships' - I have used this approach many times without problems. Don't forget to add an Index on the new table 'group_memberships' for columns: 'groupID' and 'userID'.
Option 2 is not scalable for a large amount of data, especially if groups have a lot of users.
UPDATE:
For info on Indexes, here is a good (and short) blog: https://blog.viaduct.io/mysql-indexes-primer/.
The first option is a right choice. Actually it is a materialized view for both user table and group table.
Just think materialized view as a extra table or a redundant data structure that denormalizes the user properties and group properties together for quick search.
Since if we do not have the view, when we query a group id to list all its users, we have to filter millions of users to check if he/she is in the certain group. It is a performance nightmare!
Mysql has tools to build this view very efficiently. You may build secondary index on this view columns for quick search, say, group id, group name, user id, user name or something else you hope to search with.
good luck :-)

Foreign Key in SQL pivot table - database design

I am using DBDesigner 4 for designing my database relations.
I have a users table and a recipes table. One user can own many recipes but one recipe cannot be owned by many users. This relationship is shown by the user_recipes relation in the picture. (A one-to-many relationship from users to recipes).
However, recipes can be liked by users. Many users can like many recipes. This is a many-to-many relationship between users and recipes and the pivot table for this is users_like_recipes.
But when I create this pivot table, I only need the users_id and recipes_id column. The recipes_users_id column is getting added on its own and I am not able to remove it. It says the third column has come from another Relation which is defined in the model. I guess its the user_recipes relation.
When I remove the user_recipes relation, I get the pivot table like I want to.
But I need the user_recipes relation too!
Please. Any help would be appreciated.
I would suggest removing user_id as a primary key from from the recipes table. Currently the combination if id and user_id provides identification for your recipes table. In this situation multiple user_id's can create the same recipe id because the combination has to be unique. user_id can just be a normal column in your table. If you REALLY want to, you can make an alternate key on (id, user_id) but you do not need it because the id is unique.

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

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

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.

Boolean and String Values in the same table

I'm designing my first good sized project and I want to be sure I'm on the right path here so I thought I would run it by the community.
I have vendors that submit products to companies. The vendors choose which company they want to submit to and that brings up a page of questions chosen by the company. So far I have a Table of companies, a table of vendors, and table of products. Each with their own primary key, easy enough. My issue is with my table called submissions that starts to tie them all together for each new submission. I am trying to get away from having a submission table with a thousand columns because the companies all want to ask different questions. If I have
Table Submissions
submission_id
date
product_id FK
vendor_id FK
company_id FK
and
Table Questions
question_id
question
and to bridge the many to many
Table Questions_Submissions
questions_submissions_id
submission_id FK
question_id FK
answer
Would this be the recommended path for normalization and if so is there any harm having the column answer contain boolean and string results or should I somehow break the boolean questions into another table? I'm expecting millions of rows of data over the next few years and want to be sure I dont design this wrong from the beginning. Thanks for any feedback if you see a glaring error or red flag in this design.
So far I have a Table of companies, a table of vendors, and table of products. Each with their own primary key, easy enough.
Each row has its own id number. That's not quite the same thing as you'd get by normalizing a relation. In a relational database, the important thing is not identifying a row, it's identifying what the row represents.
So, for example, this table
Table Questions
question_id
question
could quite easily end up with data that looks like this.
question_id question
--
1 What is your name?
2 What is your name?
3 What is your name?
4 What is your name?
5 What is your name?
Each row is uniquely identified, but each question (the important thing) is not. You need a unique constraint on {question}.
I have vendors that submit products to companies.
Table Submissions
submission_id
date
product_id FK
vendor_id FK
company_id FK
You need a unique constraint on either {product_id, vendor_id, company_id} or {date, product_id, vendor_id, company_id}.
You also need a table of vendor products. Your table allows a vendor to submit any product--including every product they don't sell--to a company.
The vendors choose which company they want to submit to and that brings up a page of questions chosen by the company. (Emphasis added)
Nothing in your schema stores the questions a company has chosen.
is there any harm having the column answer contain boolean and string results
You can express just about any common data type as a string. But with this structure, you can't constrain boolean values to just two values. If you add the possibility of numeric results, you can't constrain them to sane values, either.
This is certainly one way to go about it, and it looks pretty good.
You can do some clever things with the answer and some if statements in the query to handle the different types of answers, but it does add some complexity to the solution, so you should think about what you are trying to do with the answers.
For Boolean, you can just as easily get away with "true" or "false" in the varchar field, and do a count on them. If you needed to get answers that are numeric or dates, for sums or averages directly in the query, you could split the answer into types.