Storing list of strings in MySql column - sql

I have a users table which contains data for registered users, each row represents a user. One column in particular should contain a list of groups the user is part of, at the moment that column is of TEXT type and I'm storing that list as a string where groups are separated with a semicolon, something like:
admin;moderators;devteam
And I was wondering: "Is this a good idea?", is there a better/safer way to do this that doesn't require a lot of effort to implement or is this "ok"?
Here is a pic of the table as of now:

And I was wondering: "Is this a good idea?"
Short answer: probably not.
Why
If you will ever need to do any manipulation on that column, you will find yourself in big trouble. Simply selecting all users in a group will require some operations on a string (usually not performance-friendly). Same will hold true for sorting, joining and all the other operations SQL is great for.
Solution
What you describe is a typical example of N:N relationship, where each user can belong to multiple groups and each group can have multiple users in it.
The 'standard' way of modeling this relationship is creating a new table, where each row will represent a user belonging to a group. The columns will be group and userID.
With data from your example
userID | group
--------|----------
1 | admin
1 | moderator
1 | test
This allows to have one row for each user in the users table, and getting the groups of a specific user is as simple as
select group
from user_groups
where userID = '1'

Related

SQL Best way to return data from one table along with mapped data from another table

I have the following problem.
I have a table Entries that contains 2 columns:
EntryID - unique identifier
Name - some name
I have another EntriesMapping table (many to many mapping table) that contains 2 columns :
EntryID that refers to the EntryID of the Entries table
PartID that refers to a PartID in a seprate Parts table.
I need to write a SP that will return all data from Entries table, but for each row in the Entries table I want to provide a list of all PartID's that are registered in the EntriesMapping table.
My question is how do I best approach the deisgn of the solution to this, given that the results of the SP would regularly be processed by an app so performance is quite important.
1.
Do I write a SP that will select multiple rows per entry - where if there are more than one PartID's registered for a given entry - I will return multiple rows each having the same EntryID and Name but different PartID's
OR
2.
Do I write a SP that will select 1 row per entry in the Entries table, and have a field that is a string/xml/json that contains all the different PartID's.
OR
3. There is some other solution that I am not thinking of?
Solution 1 seems to me to be the better way to go, but I will be passing lots of repeating data.
Solution 2 wont pass extra data, but the string/json/xml would need to be processed additionally, resuling in larger cpu time per item.
PS: I feel like this is quite a common problem to solve, but I was unable to find any resource that can provide common solutions or some pros/cons to different approaches.
I think you need simple JOIN:
SELECT e.EntryId, e.Name, em.PartId
FROM Entries e
JOIN EntriesMapping em ON e.EntryId = em.EntryId
This will return what you want, no need for stored procedure for that.

How to deal with one single cell containg multiple values?

I'm having an exercise requiring to create two table for a travel business:
Activity
Booking
it turns out that the column activities in the Booking table references from the Activities table. However it contains multiple value. How do I sort it out? If I insert multiple rows there will possibly duplication in the Booking's primary key.
As Gordon mentioned you should refactor your tables for better normalization. If I interpret your intent correctly this is more like what your schema should look like. Booking should only contain an ID for adventure and an ID for Customer. You will add a row to [AdventureActivity] for each activity booked on a [Booking]. With this design you can JOIN tables and get all the data you require without having to try to parse out multiple values in a column.

Best database structure for multiple value attributes

I'm using PostgreSQL and I currently have 2 models.
Users (user_id, user_name),
Players (player_id, player_title, player_description)
I want to add the feature for users to add characteristics to players and other users. I was thinking to make a new table called Characteristics (characteristic_id, characteristic_description, user_id, player_id).
Each user can add multiple characteristics to multiple players. I read that adding multiple values to 1 row is not optimal for databases so my second option is to have multiple characteristics stored within the Characteristics table. But still I find this redundant because the values are being repeated.
Is there a better way to structure my database?
Example:
The Characteristics table might look like this:
characteristic_id characteristic_description user_id player_id
1 good 1 1
2 bad 1 2
1 good 2 1
1 good 2 2
I find this redundant. Is there a better way? I also don't know how to add the feature for users to add characteristics to other users.
Thanks

3 boolean fiels or 1 field with 3 values - Relational Model DB

This might be a very simple question but I wonder which would be the better way to do it under the relational model point of view.
I have 3 types of users:
Customer
Staff Member
Super Customer
All of them have the exact same fields. I have all of them in the same users table, which also makes things easier to work with the framework I'm using.
My question is: is it better to use 3 different boolean fields to difference each type of user or just one field with 3 values?
Currently i have 3 boolean fiels: admin, staff, superuser.
Would that be more clear than creating just only 1 field with 3 values? (for example, 1 for admin, 2 for staff and 3 for superuser)
Thanks.
I suggest one field perhaps a foreign key to a UserType table, something like this:
-- UserType table
-- UserTypeID INT -- PK
-- Type NVARCHAR(50)
and in you user table add one field UserTypeID.
Some users prefer readability so use a one character char field instead of an integer ID when they know the types list will be relatively short.
If a user can belong to only one user type: Use one field with three values.
If a user can belong to more than one user type: Use three boolean fields.

How to display multiple values in a MySQL database?

I was wondering how can you display multiple values in a database for example, lets say you have a user who will fill out a form that asks them to type in what types of foods they like for example cookies, candy, apples, bread and so on.
How can I store it in the MySQL database under the same field called food?
How will the field food structure look like?
You may want to read the excellent Wikipedia article on database normalization.
You don't want to store multiple values in a single field. You want to do something like this:
form_responses
id
[whatever other fields your form has]
foods_liked
form_response_id
food_name
Where form_responses is the table containing things that are singular (like a person's name or address, or something where there aren't multiple values). foods_liked.form_response_id is a reference to the form_responses table, so the foods liked by the person who has response number six will have a value of six for the form_response_id field in foods_liked. You'll have one row in that table for each food liked by the person.
Edit: Others have suggested a three-table structure, which is certainly better if you are limiting your users to selecting foods from a predefined list. The three-table structure may be better in the case that you are allowing them the ability to enter their own foods, though if you go that route you'll want to be careful to normalize your input (trim whitespace, fix capitalization, etc.) so you don't end up with duplicate entries in that table.
normally, we do NOT work out like this. try to use a relation table.
Table 1: tbl_food
ID primary key, auto increment
FNAME varchar
Table 2: tbl_user
ID primary key, auto increment
USER varchar
Table 3: tbl_userfood
RID auto increment
USERID int
FOODID int
Use similar format to store your data, instead a chunk of data fitted into a field.
Querying in these tables are easier than parsing the chunk of data too.
Use normalization.
More specifically, create a table called users. Create another called foods. Then link the two tables together with a many-to-many table called users_to_foods referencing each others foreign keys.
One way to do it would be to serialize the food data in your programming language, and then store it in the food field. This would then allow you to query the database, get the serialized food data, and convert it back into a native data structure (probably an array in this case) in your programming language.
The problem with this approach is that you will be storing a lot of the same data over and over, e.g. if a lot of people like cookies, the string "cookies" will be stored over and over. Another problem is searching for everyone who likes one particular food. To do that, you would have to select the food data for each record, unserialize it, and see if the selected food is contained within. This is a very inefficient.
Instead you'll want to create 3 tables: a users table, a foods table, and a join table. The users and foods tables will contain one record for each user and food respectively. The join table will have two fields: user_id and food_id. For every food a user chooses as a favorite, it adds a record to the join table of the user's ID and the food ID.
As an example, to pull all the users who like a particular food with id FOOD_ID, your query would be:
SELECT users.id, users.name
FROM users, join_table
WHERE join_table.food_id = FOOD_ID
AND join_table.user_id = users.id;