having trouble with foreign key queries - mysql

I'm new to SQL and I'm having a hard time figuring out how to execute queries with foreign keys on MySQL Workbench.
In my example, I have three tables: people, places, and people_places.
In people, the primary key is people_id and there's a column called name with someone's name.
In places, the primary key is places_id and there's a column called placename with the name of a place.
People_places is a junction table with three columns: idpeople_places (primary key), people_id (foreign key), and places_id (foreign key). So this table relates a person to a place using their numerical IDs from the other two tables.
Say I want the names of everyone associated with place #3. So the people_places table has those associations by number, and the people table relates those numbers back to the actual names I want.
How would I execute that query?

Try this to find all the people names who are associated with place id 3.
SELECT p.name
FROM people as p
INNER JOIN people_places as pp on pp.people_id = p.people_id
WHERE pp.places_id = 3

OK, so you need to "stitch" all three tables together, yeah?
Something like this:
select people.name
from people -- 1. I like to start with the table(s) that I want data from, and
, people_places -- 2. then the "joining" table(s), and
, places -- 3. finally the table(s) used "just" for filtering.
where people.people_id = people_places.people_id -- join table 1 to table 2
and people_places.place_id = places.place_id -- join table 2 to table 3
and places.name = "BERMUDA" -- restrict rows in table 3
I'm sure you can do the rest.
Cheers. Keith.

Related

Collection as data type in SQL

I have 2 tables one is students and the other is courses
the key for courses will be ID, however I'm having trouble connecting students with courses.
I need a datatype that will be similar to a list
so I can push an id into the data type or remove the id
also, I need a way to return * from courses if the id exists in the data type
You need to create a junction table StudentCourseAssoc
StudentCourseAssoc
----------------------
studentId
courseId
The columns being foreign keys to students to courses respectively.
That's not how you work with a relational database.
(It's possible to put comma separated values in a varchar field and use to join against a table, but it's slow and complicated to use. I have seen such attempts from time to time, and it quickly falls apart when you want to do anything other than the simplest possible queries.)
Add another table, where you reference a course and a student. Example:
StudentCourses
-------------------
StudenCourseId int autoincrement
StudentId int
CourseId int
(The autoincrement key for the relation table is optional, you can omit it and make the combination of the two foreign keys the key of the table.)
To get the courses for a student you join in the relation table. Example:
select
c.CourseName
from
Courses c
inner join StudentCourses sc on sc.CourseId = c.CourseId
where
sc.StudentId = 42

How to match csv stored in one column in mysql table?

iam a newbie in mysql
I have stored interests of user in csv format
say person_interests COLUMN stores multiple interests in person TABLE, say
$row['person_interests']='11,22,33,44'
interests TABLE 11=Music,22=Travel, and so on
Now i want to list all persons who have 11 as interest, what should i use after WHERE clause?
SELECT * FROM persons WHERE ?????
INNER JOIN
interests
ON
persons.person_interest
=
interests.interest_id
WHERE
interest.interest_id=11
It's a bad idea to store comma-separated data in SQL tables. You should use a many-to-many relation table to hold this. It makes searching and modifying the data more complicated, and matching values can't make use of indexes, so queries will be inefficient.
But if you're stuck with it, you can use FIND_IN_SET to match them.
SELECT *
FROM persons AS p
INNER JOIN interests AS i ON FIND_IN_SET(i.interest_id, p.person_interest)
WHERE i.interest_id = 11
Instead of putting all the interests in a single column, you should have a relation table:
CREATE TABLE person_interests (
person_id INT NOT NULL, -- Foreign key to persons table
interest_id INT NOT NULL, -- Foreign key to interests table
UNIQUE INDEX (person_id, interest_id),
INDEX (interest_id)
);

multiple column values in mysql

I need to make a table 'Movies' which will have columns:
ID Title Description Category etc
And another one called 'Movie_Categories' containing, for example
ID Category
1 Action
2 Adventure
3 Triller
but since category in table Movies will have multiple choices what is the correct way to do this?
should i use comma-separated values like someone said in this post Multiple values in column in MySQL or is there a better way?
This is a many-to-many relationship.
You need a join table to make it right, such as :
CREATE TABLE film_category (
category_id int,
film_id int,
PRIMARY KEY (category_id, film_id)
);
DO NOT GO FOR COMMA-SEPARATED VALUES. NEVER.
Having said that. Bear in mind that when you have a so called many-to-many relationship, that is, a relationship where you can have one category with many movies and one movie with many categories, you will always need to generate an additional table.
This table will only need the Primary Keys of each of the other 2 tables and will have a compound key.
So the schema will end up being:
Movies(ID, Title, Description, Category)
Categories(ID, Category)
Movies_Categories(ID_Movie, ID_Category)
In bold are the primary keys.
In order to get all the categories for a movie you will just have to join each of the three tables.
A final comment about having multi-valued fields is that your table will not be in First Normal Form which will, sooner or later, give you lots of headaches.
The last thing to do is have a non normalized table by storing comma separated values.
*You should have a table movies and a table for categories.
You should create a mapping table which will map the movieId to the categoryId*

Is my database rational correct? one Primary key to Multiple foreign keys?

I have an idea that I want to execute and am very rusty on my database design when it comes to the relationships between tables. I want to be able to type in 3 ingredients into 3 <input type="text"> fields and search for all the recipes with those ingredients.
I have 3 tables...
ingredients
recipe
menu
the columns that are bold are my primary keys and i want the columns in italics to be the foreign keys.
Example - iName is the primary key to iName1 iName2 and iName3.
INGREDIENTS
iName - iType
RECIPE
mName - iName1 - iName2 - iName3 - method
MENU
mName - mDiscription - mAllergy
Are the relationships between my tables efficient enough for what I want to do? and what would the join query be if I want to for example
SELECT mName, mDiscripton, mAllergy
FROM menu
WHERE iName1 = input etc etc
I already have a one table version of the database and the query I'm using works fine; I just want to redesign my database and modify my query to suit.
Your design is missing one table to be efficient; remove iName1 to iName3 from your recipe table and add a mapping table "recipe_ingredients" with foreign keys for recipe and one ingredient. You will then have one to many rows in that table for every recipe (look at my example). But: You can easily search for all recipes where an ingredient is used. And you can use 10000 ingredients for one recipe if necessary.
How is the table menu related to recipes? Does a menu always consist of one recipe? Otherwise also add a mapping table for that relation.
SELECT mName, mDiscription, mAllergy
FROM menu
JOIN recipe ON recipe.mName = menu.mName
JOIN recipe_ingredients ON recipe_ingredients.mName = recipe.mName
WHERE recipe_ingredients.iName = 'whatever'
Please don't use 1..n colums to save a n..m connection between two tables.
As you can use one ingredient in different recipes, you will need a matching table.
Those are often called table1_2_table2, or in your case recipe2ingredient.
In there you store the primary keys from both tables (in most cases as a combined primary key on that table, as it often makes sense)
The same should go for menu and recipe, since you could want to use a recipe in several menus.
So
Table 1 - Menu (ID, Name, ... whatever columns you need on top of that)
Table 2 - Recipe (ID, Name, ...whatever columns you could desire)
Table 3 - Menu2Recipe( IdMenu, IdRecipe)
Table 4 - Ingredient (ID, Name, measurement unit)
Table 5 - Ingredient2Recipe( IdRecipe, IdIngredient, Amount )

sql to populate newly created link table

I would be really grateful if somebody could help me out with this..
I actually have 2 tables in my database: books and authorlist.
The book table contains a field 'book_aut' which contains the foreign key of the authorlist table.
The authorlist table has only 2 fields, the primary key and the 'authors' column which contains a list of names.
I have to modify the table structure so that books table is linked to an authors table via a link table called 'lnk_book_author'
So my first task is to create a new table called 'authors' which contains 3 fields - primary id, name, surname, which i already did.
Next, i created the link table called 'lnk_book_author' and this one contains 3 fields, the primary id, book_fk, author_fk. The book_fk and author_fk refer to the id of the book and author respectively.
My problem is that i have more than 6000 entries in the books table and i would like to know how to populate the link table with the book id and the author id.
Is there a way of doing that using sql instead of manually populating the lnk_book_author table.
Hope i was clear enough..
Thanks a lot for any suggestion provided.
I'm infering the IDs already in your new [authors] table mean nothing with regards to the old tables. If that's the case you need to relate the records by the Name. And there I need to assume that the names are entered Identically. If they're not, it may not be possible to do. We'd need to know a lot more specifics to be sure...
INSERT INTO
lnk_book_author
SELECT
Books.PrimaryKeyFieldName,
Authors.PrimaryKeyFieldName
FROM
Books
INNER JOIN
AuthorList
ON Books.BookAut = AuthorList.PrimaryKeyFieldName
INNER JOIN
Authors
ON CONCAT(',', AuthorList.Authors, ',') LIKE CONCAT('%,', Authors.Name, ',%')
Something like that ?
INSERT INTO lnk_book_author(book_fk,author_fk)
SELECT b.book_id,a.author_id
FROM books b INNER JOIN authorlist a
ON b.book_aut=a.author_id
Try this it should work:
INSERT INTO lnk_book_author (book_fk, author_fk)
VALUES ((SELECT Id FROM books), (SELECT Id FROM authors))
And by the way there's no point having an Id column in the lnk_book_authors table, you may as well just make the foreign keys a composite primary key.
UPDATE
Sorry I realise that would only work with one record, try the following SQL:
INSERT INTO lnk_book_author (book_fk, author_fk)
SELECT books.Id, authors.Id
FROM books, authors