Issues setting up a N-M relationship - mysql

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.

Related

Look for MySQL table structure recommendation

I have two table now:
conference table: id, name
people table: people_id, name
what I want to do
I want to make a new table so that I can get all attend people by conference id but also get all conference a specific man attended by people_id.
what I have thought
make a new table whose columns is all the people's id, and insert each conference as row, if the people shows in conference, we make it 1, otherwise 0. But it's too sparse and difficult to show which people attend a specific conference because we have many columns.
UPDATE
thanks for your comment. Now I create a table like this:
I think it's much better than the table before.
How about this?
A join table called conferences_people.
cp_id | conference_id | people_id
-------+---------------+-----------
1 | 1234 | 1
2 | 1234 | 4
3 | 1234 | 5

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

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.

How to remove redundant records in the given table, using SQL

How to remove redundant records in the given table, using SQL?
FROM | TO | TIME
========================
USA | CHINA | 4
USA | AFRICA | 2
CHINA | USA | 4
CALI | NEWZLND | 3
Here the USA to CHINA & CHINA TO USA are redundant records, I require only one of them to be in the final table. How must I phrase an sql query for this?
Try it like this.
Fiddle: http://sqlfiddle.com/#!9/c3211/2
Btw: Changed your column names. Do not use reserved words like FROM, TO and TIME...
CREATE TABLE tbl(FromColumn VARCHAR(100),ToColumn VARCHAR(100),TIMEColumn INT);
INSERT INTO tbl VALUES
('USA','CHINA',4)
,('USA','AFRICA',2)
,('CHINA','USA',4)
,('CALI','NEWZLND',3);
SELECT *
FROM tbl AS tbl
WHERE (SELECT COUNT(*)
FROM tbl AS x
WHERE x.FromColumn>x.ToColumn
AND x.FromColumn=tbl.ToColumn
AND x.ToColumn=tbl.FromColumn
AND x.TIMEColumn=tbl.TIMEColumn
)=0;
It sounds like you have a reflexive relationship, similar to "Person1 is a friend of Person2" - where it's implied that "Person2 is a friend of Person1", and you don't want to store both records. Assuming that it doesn't matter which one you store, you can delete the duplicates. Here, I keep the one where Person1 comes before Person2:
CREATE TABLE Friendship(
Person1 varchar(128),
Person2 varchar(128),
PRIMARY KEY(Person1, Person2)
);
DELETE FROM Friendship
WHERE EXISTS(
SELECT *
FROM Friendship as reflex
WHERE Friendship.Person1 = reflex.Person2
AND Friendship.Person2 = reflex.Person1
AND Friendship.Person2 < Friendship.Person2
);

How to design one user "likes" another?

I would imagine this is kind of like friends, but doesn't need to be two-way. So like this:
from_user to_user
-------------------
John Mary
Mary John
John Susan
Mary Dave
I was curious if there were any issues with doing it as shown below.
user1 user2 mutuality
--------------------------------
John Mary 2
John Susan 1
Mary Dave 1
The second seems like it would have more complicated queries and checks, but wouldn't it end up saving space? For example, if Susan ends up falling for John one day, you'd check user2 for Susan and user1 for John. If it exists, update the mutuality to 2. If not, insert a new row [Susan, John, 1]. Something like that?
What's the best way of doing this?
I would choose the first method. You will not end up saving enough space with the second method to be an issue. Since each choice (like) is an action, having a separate record to store that action matches the work flow. John likes Mary, add a record. Mary likes John, add another record. Mary no longer likes John, delete that single record. This is easier to maintain (for me). I find keeping things in smaller granular parts keeps it simple.
In terms of design, I would recommend that instead of using string names in the likes table, you should have a users table with each user have a primary key id (unique). This way, users can modify names without breaking the relationships.
The table data would look like this:
Users table
id Name
1 John
2 Mary
3 Susan
4 Dave
Likes table
From To
1 2
2 1
1 3
2 4
The tables would have the following structure
users
-----
id (integer autoincrement)
name (varchar)
likes
-----
id (integer autoincrement)
fromid (integer)
toid (integer)
The sql would look like this to produce the list
SELECT f.name as fromName, t.name as toName
FROM (likes JOIN users AS f ON likes.fromid = f.id)
JOIN users AS t ON likes.toid = t.id;
The second method allows the following anomaly:
user1 user2 mutuality
--------------------------------
John Mary 2
Mary John 1
Do John and Mary like each other mutually (as implied by the first row), or just Mary likes John uni-directionally (as implied by the second row)?
The first method doesn't suffer from such inconsistencies, and data integrity is generally more important than saving some space.
BTW, if you introduce an integer surrogate key and reference it from the junction table (instead of the actual names), the junction table will become much leaner, negating much of the space advantage of the second method.

What's the best db structure to represent the relationships within a family if the base-object is a Person

I have a large DB full or people called PERSONS.
I want to store their relationship to one another in a separate table.
I am thinking something like this:
FAMILY
PERSON_IDS: 123, 345, 678
RELATIONS: self, brother, daughter
Using a 'self' flag to indicate the person referring the relation-ship from. So, in the example 123 would be a man, 345 is his brother and 678 is a woman, his daughter. I.e, the gender information could be derived from the relationship.
Is this the right way to go about it?
Or would it be more efficient to have only 2 PERSONS per row and one relationship-type
PERSON_IDS: 123, 456
RELATION: brother
-
PERSON_IDS: 123, 678
RELATION: daughter
Or is it better to have a male/female field per person and the relation-ship table only specify eg "sibling".
Or should I have a table with PARENTS only and store the gender with the PERSON?
TABLE PARENTS:
PARENT_ID: 123
CHILD_ID: 678
The aim is to display related people when a Person is displayed. The design should be optimized for performance & speed rather than ease of administration.
Thanks for your help.
It's a many-to-many relationship: each person can have many relatives and also be a relative of many people. Assuming your Person table has a primary key named Id, you could have a table, which holds the relationship between two people as well as the kind of relationship they have. It would be useful to also have a table with all the possible kinds of relationships, something like this:
Relationship(Id, Kind)
Family(Person_Id, Relative_Id, Relationship_Id)
So if you have the following data for Person and Relationship tables:
Person: Relationship:
Id | Name Id | Kind
1 | John 1 | Father
2 | Mike 2 | Sister
3 | Susan
and the following for Family table:
P_Id | Rel_Id | Relation_Id
1 | 2 | 1
1 | 3 | 1
2 | 3 | 2
Family table is saying that John is the father of Mike and Susan, and that Mike's sister is Susan. I think this could be a good approach, but of course, as almost everything in databases design, this solution is arguable.