Designing a schema for players and tournaments - mysql

I am beginner in SQL, I have a simple MySQL database which contains two tables:
Players (id, name)
Tournaments (id, name, participants)
I want to save information about participants of every tournament. The first idea that I have is that participants should contain a large number of id fields from the players table but that doesn't seem good.
How should I design this in the correct way?

Make another table called Participants with two fields. Player_ID and Tournament_ID. This table can hold as many lines as it needs to to correlate who played when, and you can cross reference it as needed.

Remove "participants" from the second table and add a third table: TournamentPlayers (playerid, tournamentid).
You should avoid storing multiple values in one field. That would break the first normal form of database design (1NF), which states that only atomic values can be stored in one field. Relational database systems are not well-suited to cope with non-normalized data, and you will have a hard time writing queries for non-1NF tables.

Related

Database design - Many tables with unique tags or one table with all of them?

I'm working on the database (MySQL) - car dealership. Since the product (car) has a lot of features and unique values (gearbox, model, manufacturer...), I wonder, how to create a well designed database for it.
Should I use:
Table cars
columns -> id, name, manufacturer, model, gearbox...
Or:
Table cars
columns -> id, name, manufacturer_id, gearbox_id...
Table manufacturers
columns -> id, name
Table gearbox
columns -> id, name
There are a lot of unique values as I mentioned and I think it's not good to store them again and again, but if I create a lot of tables + link them with link table to product table (car), there will be a lot of joins when I make a query to get all of the values.
And these are only few of them, there are much more values I need to store for every product in the database.
You have 3 options here:
You could store each car as a separate table and then have a row corresponding to the gearbox, etc. This is awful, no one does it, don't do it.
You could serialize all the gearbox, etc. data as json strings and put them in your car cells. This is also awful, some people have stupidly done this, but not that often. Don't do it.
You could do things the normal, good way and implement separate tables for every class of object with foreign keys linking them. This is the way to go.

Multiple Tables Vs one table for e-commerce product store combination

I am running an e-commerce site with multiple stores and each store having its products. I currently have a table called product-store which has a list of all product id referencing the products name and description from a different table , prices etc and their corresponding store ids. This table could have same product repeating multiple times if multiple store carry it.
I am mooting the idea of having a separate table for each store(product-store1, product-store2) rather than having all stores in one product-store table. I could be adding 100 stores and hence 100 tables like this. The structure of each table is the same but the reason why I am thinking of doing this is for better encapsulation of data from the other stores. However this would also mean identifying the corresponding table first for the store and then fetching the data.
I need help in assessing if this is a right approach and how I can measure the two approaches.
There are very few good reasons for splitting a table into multiple tables. Here are reasons not to do it:
SQL is optimized for large tables, but not for lots of small tables with the same structure. (With small tables, you end up with lots of partially filled data pages.)
Maintenance is a nightmare. Adding a column, changing a data type, and so on has to be repeated many times.
A simple query such as "How many stores sell a single product?" are problematic.
You cannot have a foreign key relationship into this table, for instance, to have a history of prices or discounts on the product in each store.
A single table is almost always the best way to go.
I guess it also depends on if the products might be shared across different stores. I would not go the way of creating x tables for x stores, but a general structure to be able to hold all the information.
If so, you could set up at least three tables:
product (holds all the generic products information, shop independent)
store (information about the stores)
store_product (links the products to the stores)
This way you can add as many products / stores to your system without having to change database structure (which is bad anyways).
To answer some of your assumptions:
Encapsulation of data from different stores is rather selecting a subset of data that choosing different tables.
whenever you need some additional information (not being thought of in the beginning) for either stores or products, its easier to add by referencing the new table to stores/products instead of having to multiply those changes by the amount of stores.

SQL Structure for several tables

I need to create a mySQL database that keeps information about vehicles. My instincts were to create one table with as many columns as I need, but then I read about the problems in doing so. After researching, I think I'm on the right track with the following structure:
Vehicles Database
Motorcycles Table
id|road|cruising|touring|
Cars Table
id|sedan|coupe|hatchback|
Colours Table
id|green|red|blue|black|silver|white|yellow|etc..
Make Table
id|ford|chevrolet|gm|toyota|bmw|etc..
Quadrant Table (1-4)
id|motorcycle|car|truck
So basically I have a table for the objects - cars, motorcycles, trucks - and then tables for the fields/properties - Colour, Make, etc. and then a table for the Quadrant the vehicle is seen in, with a value of 1-4 where each row is an instance of only one vehicle.
The problem I'm having is understanding where the primary and foreign keys need to be in order for me to be able to organize the data:
By each individual vehicle selected along with its fields
By quadrant, showing each vehicle and their respective fields
The user counting cars should be able to input the vehicle type, the field values and the quadrant it's seen in and the db gets populated - and then I need to call the data by quadrant to analyze the data.
I don't know if or how a JOIN statement will be used? How do I go about structuring this database to suit my needs?
FWIW, dba.stackexchange says basic SQL questions belong here, so I hope I'm in the right place.
Can you tell, what is your exact need for the database i.e what functionality you need.
I suggest tables like following:
1) Vehicle table:
id|type which might contain info like 1|Motorcycle, 2|Car
2) category table:
id(foreign key)|category|color which contain info like 1|touring|Black, 2|Car|Hatchback
3) Make table: (if you need to create another table)
id (foreign key to table 1)|Make
I have not understood the functionality of quadrant table but with these 3 table you can create views according to your needs and play around with it.
From my point of view:
I will create a table CarBrands, with columns Id, BrandName, Description, which will serve as a look up.
Then I will create another table Cars with Id, CarBrandId, ColorId (From Colors Table), Description, which is your table with user records.
Same with your other entities. I suggest you search about Entity Relationship Diagrams, a good way of helping you come up with a good design.
Also look at this old StackOverflow question, this will help you.

Best approach to normalizing an existing multi-column, multi-string table?

I am new to mysql, so help would be much appreciated :-)
Let's take the movie db example:
movie_td (mov_id auto_increment pk, title, year, duration)
actor_td (act_id auto_increment pk, name)
director_td (dir_id auto_increment pk, name)
movie_actor_td (movie_id fk, actor_id fk)
movie_director_td (movie_id fk, director_id fk)
I understand how to insert a .csv type of a file into a single td where all the names are stored in one column, but it's a little bit confusing to do this in a normalized format. If I already have all the data stored in one table, does it make sense to create a static mov_id first so that I can reference the rest of columns to it? Or is there a better way of doing this?
Thanks!
If you will store all the data in one table, you will face issue if any of your movie has multiple actors or has more than one directors.
This normalized database approach is better to avoid insert, update and delete anomalies of redundant data in database tables.
Also, you will have to write same name(for actor/director) for each row of the movie if same actor is concerned to many movies. Thus, updating actor/director name in a particular row and not in other rows will create inconsistency in the names of actor/director in the table.
If you go by definition, a relation is in first normal form if the domain of each attribute contains only atomic values, and the value of each attribute contains only a single value from that domain. (Source: wikipedia.org).
Hence, when you insert multiple values separated by comma in a row, you are violating the first NF itself! This is because there is a many-to-many relationship among data and you are not mapping it correctly.
Moreover, you ask a very basic question- If I already have all the data stored in one table, does it make sense to create a static mov_id first so that I can reference the rest of columns to it? - well, if you just want to have all the data stored in one table, why not go for XML? You will have one single file storing all the relevant data. But the fact is, you can not run a complete application using XML. XML has different purpose, database tables have different purpose. You do need a data structure that can be queried however you want and not worry about how the storage is happening. I would suggest you read Korth's book on database design.
Coming over to designing databases and table structures, it doesn't matter whether you know how to store a .csv file into a column or not. What matters is how long it is going to take to develop the complicated code to fetch values from the CSV column. It is always better to write a few simple queries than complicated search loops to fetch values.
Let's look a the example you have posted. I'd take only three tables from it.
Consider the table movie_td (I don't understand the reason behind the _td part but I'll stick to it because you posted it.) This table stores information about a movie. Now, in the real world, a movie may have multiple attributes (columns) like title, release date (now, that too depends on the region where it is released, it may have multiple release dates as per region, it's a different story altogether), running time, name of the director(I've only watched movies by single director or director duo so far. I'm yet to see a multi-director movie ;), etc.
We must consider two facts here:
A movie has multiple actors portraying multiple characters.
An actor may have acted in multiple movies.
This gives us with a many-to-many relationship between actors and movies and this is where the table movie_actor_td comes into picture. This table stores which movie has which actor cast in it, with movie_id and actor_id each being a foreign key. A movie may have multiple entries in this table against those many actors. An actor may also have multiple entries in this table against those many movies, so a mutual many-to-many relationship is maintained among these.
A major reason to have this sort of structure is querying the tables. If you store the names of the actors comma separated in the movies table, you have no means to drill down data for the actors using actor_id- you cannot get the actor's other details like their date of birth and other biodata.
What if someone asks you how many movies has the actor foo done? Would you go looking for the actor's name in the CSV column in every row? How fast would it be?
But now that you have the given table structure, you can find that out by a simple query like this:
SELECT count(*)
FROM movie_actor_td
WHERE actor_id = (SELECT actor_id
FROM actor_td
WHERE name = 'foo');
Let's consider an even more complex example. For this, I'd take the freedom to add a column character_name to the table movie_actor_td, as an actor usually plays a single character in a movie. So your movie_actor_td table would look like:
movie_actor_td (movie_id, actor_id, character_name)
So now, there is an actor who played James Bond in movie Goldeneye that was released in 1996. I don't know his name. I want to know how many movies has he done in year 2002. I'd simply put a query like:
SELECT COUNT(*)
FROM movie_actor_td
WHERE actor_id = (SELECT actor_id
FROM movie_actor_td
WHERE movie_id = (SELECT movie_id
FROM movie_td
WHERE name = 'Goldeneye'
AND release_year = 1996)
AND character_name = 'James Bond');
Can you fetch that so easily if you have all the data stored in a single CSV column? I doubt that. I'd suggest you continue with the current schema in hand.
EDIT
You ask about creating a static mov_id first and the reference all the other columns to it. I think you need to read further about primary keys, foreign keys and database constraints first. Then read about auto-increnemted column values in MySQL.

What's the best approach to designing a database that keeps track of orders and wish lists?

The best way to describe this scenario is to use an example. Consider Netflix: do they
store their orders (DVD's they mail out) in a separate table from their member lists (NOT members table, but a joiner table of members and movies--a list of movies each member has created), or are orders distinguished by using additional information in the same row of the same table?
For those not familiar with Netflix, imagine a service that lets you create a wish list of movies. This wish list is subsequently sent to you incrementally, say two movies at a time.
I would like to implement a similar idea using a MySQL database, but I am unsure whether to create two tables (one for orders and one for lists) and dynamically move items from the lists table to the orders table (this process should be semi-automatic based on the member returning an item, where before a new one is sent out, a table with some controls will be checked to see if the user is still eligible/has not gone over his monthly limit)...
Thoughts and pros and cons would be fantastic!
EDIT: my current architecture is: member, items, members_items, what I am asking is if to store orders in the same table as members_items or create a separate table.
Moving things from one database table to another to change its status is simply bad practice. In a RDBMS, you relate rows from one table to other rows in other tables using primary and foreign key constraints.
As for your example, I see about four tables just to get started. Comparing this to Netflix, the grand-daddy of movie renting, is a far-cry from reality. Just keep that in mind.
A User table to house your members.
A Movie table that knows about all of the available movies.
A Wishlist or Queue table that has a one-to-many relationship between a User and Movies.
An Order or Rental table that maps users to the movies that are currently at home.
Statuses of the movies in the Movie table could be in yet another table where you relate a User to a Movie to a MovieStatus or something, which brings your table count to 6. To really lay this out and design it properly you may end up with even more, but hopefully this sort of gives you an idea of where to begin.
EDIT: Saw your update on exactly what you're looking for. I thought you were designing from scratch. The simple answer to your question is: have two tables. Wishlists (or member_items as you have them) and Orders (member_orders?) are fundamentally different so keeping them separated is my suggestion.
A problem with storing orders in the members table is that there's a variable number (0, 1, or several) of orders per member. The way to do this using a relational database is to have two separate tables.
I feel like they would store their movies as follows (simplified of course):
tables:
Titles
Members
Order
Order_Has_Titles
This way an order which has a foreign key to the Members would then have a pivot table as many orders could have many titles apart of them.
When you have a many to many realtionship in the database you then need to create a pivot table:
Order_Has_Titles:
ID (auto-inc)
Order_FkId (int 11)
Title_FkId (int 11)
This way you're able to put multiple movies apart of each order.
Of course this is simplified, and you would have many other components which would be apart of it, however at a basic level, you can see it here.