Can 1 primary id link to multiple ids in one table? - mysql

I am trying to create a database schema regarding betting being played with numerous betting providers. Some betting providers have 15/13/16 etc games per pool.
E.g. Provider A (ID 1) has Liverpool Vs Man City has 1 of its 15 games and Provider B (ID 2) also has this match for one of their 13 games.
Can I record this like the following;
Match ID 1
Provider ID 1,2
Home Team Liverpool
Away Team Man.City
Bookmaker Pinnacle
Is that possible or can SQL not store to id's for 1 primary id?
I am trying to keep a record of each match for each pool so I can then record what the betting prices were by specific bookmakers and what the payout percentages were for future references.
Is there anyway this can be done?
E.g. Provider A (ID 1) has Liverpool Vs Man City has 1 of its 15 games and Provider B (ID 2) also has this match for one of their 13 games.
Can I record this like the following;
Match ID 1
Provider ID 1,2
Home Team Liverpool
Away Team ManCity
Bookmaker Pinnacle
Is that possible or can SQL not store to id's for 1 primary id?
Not coded yet, currently working on creating the database schema

This is a common misunderstanding with foreign keys. If you think you need to store two IDs in one record's foreign key, your foreign key is in the wrong place.
In your case, if a match can have many bettors, and a bettor can have many matches, you need a many-to-many or "junction" table, linking matches to bettors.
Your schema might look something like this:
table matches:
id | Home Team | Away Team
----+-----------+-----------
1 | Liverpool | Man.City
table providers:
id | name
----+------------
1 | Provider A
2 | Provider B
table provider_matches:
provider_id | match_id
------------+----------
1 | 1
2 | 1
Your table provider_matches now has two foreign keys, which can be enforced through foreign key constraints, linking both providers to the same match.

Related

Database design for sport scoring system

I am working on database for scoring system for my friend. I have table with games and second table with names of sports (footbal, tenis, floorball). I want to store scores of the games but I don't know how to design database for specific needs of scores.
For example:
Football score - 1:2, 2:2 (1st and 2nd half)
Tenis sets - 6:4, 7:6
Floorbal - 1:0, 3:0, 3:2 (1st, 2nd and 3rd part of the game)
I need this score linked to games table, but I need specific table columns for storing score for every game.
I think about:
Multiple tables and and foreign key, but this is not possible in mysql.
Then I think about storing data in json in one row and then parse it specifically based on sport, but probably this is not very good solution.
The only problem from my point of view is:
How create table/s for storing scores in different format based on type of sport?
Thank you for any help
E.g.:
match_id | period_id | team1_score | team2_sore
1 | 1 | 1 | 2
1 | 2 | 2 | 2
2 | 1 | 6 | 4
2 | 2 | 7 | 6
3 | 1 | 1 | 0
3 | 2 | 3 | 0
3 | 3 | 3 | 2
You mention MySQL, so it appears that you want to develop a relational database.
The first step is to define the relations. Based on your example.
A game has one sport.
A sport has zero or more games.
A game has one or more period scores.
A period score has one game.
Based on these relationships, we can define 3 tables.
Sport
-----
Sport ID
Sport name
...
Game
----
Game ID
Sport ID
Game name
PeriodScore
-----------
PeriodScore ID
Game ID
Period
Score
The primary ID fields are known as blind keys. They are auto-incrementing integers. Their sole purpose is to tie the game with the sport, and the period scores with the game. Otherwise, they have no meaning at all. The primary ID fields are the primary (clustering) keys of their respective tables.
The Sport ID in the Game table is a foreign key. This key points back to the Sport table, so you can get the name of the sport. You can create a unique index on (Sport ID, Game ID) if you ever want a list of the games for a particular sport.
The Game ID in the PeriodScore table is another foreign key. You must create a unique index on (Game ID, PeriodScore ID) so that you can retrieve the period scores in the correct order.
When you want to create a relational database, you first define the relationships, then go through a process of normalization.

How to add a N:M relationship to my MySQL symptoms and diseases database?

I am working on a health app and I've created a database (MySQL), which stores symptoms and diseases.
There should be a N:M relationship between the symptoms and diseases, so each symptom could have multiple diseases and vice versa. Symptoms should also have common and less common diseases and because of that, they should have a ranking (1 to infinity). How should I design/add this new feature?
Current table structure:
disease: d_id, d_name
symptom: s_id, s_name
You require an ordinary Associative table to resolve the logical n::m relationship. The PK of such tables is the two PKs of the parent tables. That gives the required row uniqueness, etc.
Second, it has data columns, so it is no longer an Associative table, it becomes an ordinary table, a binary relation (two parents).
I understand that in the symptoms-per-disease or diseases-per-symptom result sets, the rows will be ranked, but the column containing the value in the table is not rank. It is an indicator of weight given to each symptom::disease. The rank is the order in the result set, from 1 to no-of-rows, it is derived, it will change all the time. The weight is a stable value in the database, from 1 to infinity.
I recommend you give all the constraints names.
Could you show me a query example regarding the constraint names?
Sure. Simply use explicit CONSTRAINT clauses, after the columns, rather than placing each constraint with a single column. You have to do that in the case of compound Keys, such as this one. The naming convention I use for FK constraints is:
<parent>_<verb_phrase>_<child>_fk
The relevance of named constraints, as well as this naming convention, will become clear to you when you have many tables, when you are administering the various objects in the database.
The Verb Phrase comes from the data model (had the data been modelled), it describes the Action between the subject table and the object table.
In SQL the DDL looks like this (you will have to translate for your NONsql):
CREATE TABLE symptom_disease ( -- associative table
s_id INT NOT NULL,
d_id INT NOT NULL,
weight BIGINT NOT NULL, -- plus a data column
CONSTRAINT UC_PK -- named constraints
PRIMARY KEY ( s_id, d_id ),
CONSTRAINT symptom_indicates_symptom_disease_fk
FOREIGN KEY ( s_id )
REFERENCES symptom ( s_id ),
CONSTRAINT disease_is_indicated_by_symptom_disease_fk
FOREIGN KEY ( d_id )
REFERENCES disease ( d_id )
)
For the PK, you want U Unique and C Clustered. I have chosen ( s_id, d_id ) on the assumption that you will have more queries that look up diseases per symptom (than symptoms per disease). If the converse is true, change the clustering to ( d_id, s_id ).
You need another table, lets call it symptom_disease which shows the relation between a symptom and a disease. In another word each row of this table will show that a symptom is related to a disease with a specified rank. So look at this:
symptom_disease (s_id,d_id,rank);
In which s_id is foreign key to symptom.s_id and d_id is a foreign key to disease.d_id.
Lets have an example. Consider we have tow diseases like this:
| d_id | name |
| 1 | cold |
| 2 | cancer |
And tow symptoms:
| s_id | name |
| 1 |Stomach Ache|
| 2 | headache |
Now look at symptom_disease table:
| s_id | d_id | rank |
| 1 | 1 | 0 |
| 2 | 1 | 0 |
| 1 | 2 | 5 |
thees rows shows that stomach ache relates to cold by rank of 0 and to cancer by rank of 5; also headache relates to cold by rank of 0.

Issues setting up a N-M relationship

Using MySQL I'm trying to set up a 1 to many relationship using data that has already been uploaded into the database. For examples sake, lets say I have a list of names in one table and I want connect them to a lists of places they have been. Obviously 1 person can go to many different places, but i'm having an issue getting this set up.
-----Name-----------ID---------
John Smith 1
Joe Random 2
Seth Guy 3
------------------------------
I have another table that would look like this:
-------city---------ID---------
New York 1
Chicago 2
Orlando 3
LA 4
-------------------------------
I'm looking for something like this:
--------Name--------City----------
John Smith Chicago
John Smith Orlando
John Smith New York
Seth Guy Chicago
Joe Random LA
------------------------------------
I obviously Know that John Smith has been to all 3 locations because the original file I uploaded tells me so, but I want the database to make that connection and place him their accordingly.
As noted in the comments, this is an N-M relationship, not a 1-N relationship. You need an additional "mapping" table to record the visits:
CREATE TABLE visits (
person_id INT,
city_id INT,
CONSTRAINT visits_pk PRIMARY KEY (person_id, city_id)
);
Then, you can query all the visits with a couple of joins:
SELECT person.name, city.name
FROM person
JOIN visits ON person.id = visits.person_id
JOIN city ON visits.city_id = city.id
Introduce a new table that holds the relationship.
Your schema would look something like this:
create table person (id, name)
create table city (id, name)
create table person_to_city (people_id, city_id)
Create a foreign key constraint on people_id and city_id.

Database Design - Linking student to teacher

Still working on a web application as a school project, and it just seems to keep expanding.
I have to add a layer for teachers so they can manage and coach students through the application. So, I have to link teachers to their students.
I was wondering what the best way would be to do this. I have one table for all users at the moment. The bare basics of this table are:
id | email | firstname | lastname | role
1 | s#s.s | dromiceio | mimus | 1
2 | d#d.d | tyranno | saurus | 2
3 | a#a.a | utah | raptor | 1
Role is the number I assign to them to give them certain permissions. 1 = student, 2 = teacher, 3 = admin.
Assuming that one student has one teacher but one teacher has many students, what would be the best way to design my database table?
I was thinking of creating a new table and just putting the student/teacher ids in it:
For example, if teacher Tyranno Saurus (id 2) has the two students in the table above linked to him, I would make a table like this:
pk_id | teacherid | studentid
1 | 2 | 1
2 | 2 | 3
That way, I would know that teacher Tyranno (id 2) has two students, namely the student with userid 1 and userid 3.
Then again, I have never really worked on anything like this so I was wondering if anyone could give me some insight about this and if it's possible to do this in a better way.
I'm building my app in PHP (CodeIgniter) with MySQL; if that's of importance.
Thanks a lot.
If a student has zero-or-one teacher coaching them, then I would suggest adding a CoachID column to the student table that is a foreign-key to that particular teacher. The intermediate table you've suggested doesn't do anything to simplify this simple relationship, it actually makes it that little bit more complicated.
If you were tying students to classes (where each class has multiple students and each student takes multiple classes) then an intermediate many-to-many mapping table would be a must.

Whats the most efficient way to store an array of integers in a MySQL column?

I've got two tables
A:
plant_ID | name.
1 | tree
2 | shrubbery
20 | notashrubbery
B:
area_ID | name | plants
1 | forrest | *needhelphere*
now I want the area to store any number of plants, in a specific order and some plants might show up a number of times: e.g 2,20,1,2,2,20,1
Whats the most efficient way to store this array of plants?
Keeping in mind I need to make it so that if I perform a search to find areas with plant 2, i don't get areas which are e.g 1,20,232,12,20 (pad with leading 0s?) What would be the query for that?
if it helps, let's assume I have a database of no more than 99999999 different plants. And yes, this question doesn't have anything to do with plants....
Bonus Question
Is it time to step away from MySQL? Is there a better DB to manage this?
If you're going to be searching both by forest and by plant, sounds like you would benefit from a full-on many-to-many relationship. Ditch your plants column, and create a whole new areas_plants table (or whatever you want to call it) to relate the two tables.
If area 1 has plants 1 and 2, and area 2 has plants 2 and 3, your areas_plants table would look like this:
area_id | plant_id | sort_idx
-----------------------------
1 | 1 | 0
1 | 2 | 1
2 | 2 | 0
2 | 3 | 1
You can then look up relationships from either side, and use simple JOINs to get the relevant data from either table. No need to muck about in LIKE conditions to figure out if it's in the list, blah, bleh, yuck. I've been there for a legacy database. No fun. Use SQL to its greatest potential.
How about this:
table: plants
plant_ID | name
1 | tree
2 | shrubbery
20 | notashrubbery
table: areas
area_ID | name
1 | forest
table: area_plant_map
area_ID | plant_ID | sequence
1 | 1 | 0
1 | 2 | 1
1 | 20 | 2
That's the standard normalized way to do it (with a mapping table).
To find all areas with a shrubbery (plant 2), do this:
SELECT *
FROM areas
INNER JOIN area_plant_map ON areas.area_ID = area_plant_map.area_ID
WHERE plant_ID = 2
You know this violates normal form?
Typically, one would have an areaplants table: area_ID, plant_ID with a unique constraint on the two and foreign keys to the other two tables. This "link" table is what gives you many-many or many-to-one relationships.
Queries on this are generally very efficient, they utilize indexes and do not require parsing strings.
8 years after this question was asked, here's 2 ideas:
1. Use json type (link)
As of MySQL 5.7.8, MySQL supports a native JSON data type defined by RFC 7159 that enables efficient access to data in JSON (JavaScript Object Notation) documents.
2. Use your own codification
Turn area_id into a string field (varchar or text, your choice, think about performance), then you can represent values as for example -21-30-2-4-20- then you can filter using %-2-%.
If you somehow try one of these, I'd love it if you shared your performance results, with 100M rows as you suggested.
--
Remember than using any of these breaks first rule of normalization, which says every column should hold a single value
Your relation attributes should be atomic, not made up of multiple values like lists. It is too hard to search them. You need a new relation that maps the plants to the area_ID and the area_ID/plant combination is the primary key.
Use many-to-many relationship:
CREATE TABLE plant (
plant_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
) ENGINE=INNODB;
CREATE TABLE area (
area_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255)
) ENGINE=INNODB;
CREATE TABLE plant_area_xref (
plant_id INT NOT NULL,
area_id INT NOT NULL,
sort_idx INT NOT NULL,
FOREIGN KEY (plant_id) REFERENCES plant(plant_id) ON DELETE CASCADE,
FOREIGN KEY (area_id) REFERENCES area(area_id) ON DELETE CASCADE,
PRIMARY KEY (plant_id, area_id, sort_idx)
) ENGINE=INNODB;
EDIT:
Just to answer your bonus question:
Bonus Question Is it time to step away from MySQL? Is there a better DB to manage this?
This has nothing to do with MySQL. This was just an issue with bad database design. You should use intersection tables and many-to-many relationship for cases like this in every RDBMS (MySQL, Oracle, MSSQL, PostgreSQL etc).