hello i'm trying to make two databases linked for a book review system i'm creating
for example i have a table for books and i also have another table for genres.
The books table will store all the different books and will have a foreign key of the genre it belongs to using a genre_id key or something.
When i do a query for genres i want it to display how many books are in that genre eg 2 books in the fantasy genre.
for that i would need a records column? but how do i have that auto incrementing/deleting when new records are added or deleted?
EDIT:
Wow thanks for all the help so quickly, so i understand i don't need a seperate table for records but say i wanted it to work with this
function all_get() {
$this->load->database();
$sql = 'SELECT * FROM books;';
$query = $this->db->query($sql);
$data = $query->result();
$this->response($data, 200);
}
how would i do the query to show the records each genre has instead of all the seperate books showing individually?
EDIT: I may have misunderstood, initially I thought these are really two separate questions - one on creating an auto incrementing primary key and another on how to show the number of books in each genre.
Counts
On showing the number of books in each genre as well as the name of the genre, I think you're looking for something like this:
SELECT g.genreName, count(*) from books b
JOIN genres g on g.ID = b.genreID
GROUP BY g.genreName
SQL Fiddle: http://sqlfiddle.com/#!2/a3c45e/2
Auto incrementing
As others have already commented, you don't need a separate records table, but in case you still need help with auto incrementing primary keys, here's the most basic example from W3 schools:
CREATE TABLE Persons
(
ID int NOT NULL AUTO_INCREMENT,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
PRIMARY KEY (ID)
)
You don't need a records column. You can query how many books are related to each genre:
SELECT count(*) FROM Book WHERE genre_id = :genreId;
BTW before you start you might rethink your entity relations. Is Genre <-> Book really 1:n?
Related
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*
I'm getting ready to populate a couple of tables in a movie database I have created. The Movies table has already been created. It looks like this:
movieid INT NOT NULL PRIMARY KEY
title VARCHAR(50)
link VARCHAR(100)
release_date VARCHAR(10)
It should perhaps be noted that I'm using MySQL-python and Scrapy to populate this data in the MySQL database, but perhaps that doesn't matter.
I have created three additional tables which have not yet been populated: Producers, Actors and Directors. Each of these looks like the other in that there exists id, name and movie title. So Actors looks like:
actorid INT NOT NULL PRIMARY KEY
actor VARCHAR(40)
title VARCHAR(50) <<<<------ This is the movie title from the Movies tables
Now, I would like to create a table called Movie To Actor which holds the movieid from the Movie table and the actorid from the Actor table and not have the title column existing in the Actors table.
I figure there are two ways to do this:
First Way:
Get all of the data into the Actors table with title acting as a foreign key and to THEN create the Movie To Actor table, adding the appropriate ids where movies.title is equal to Actors.title and to then drop the title column from Actors.
Second way:
Do this as I am populating the data. First create the Movie to Actor table, set up key constraints and set this to auto update as the data is added to Actors table. I would prefer this as it makes things significantly easier and I think is stylistically better. Was hoping someone could instruct me on how I would go about doing this. I think I can figure out how to extrapolate instructions in MySQL into MySQL-python, but would need help on how to do the former.
A couple points first off:
Unless you're manually populating the actorid and movieid fields in the actors and movies tables you should have an auto_increment on those columns.
If you're using movies.title to link to anything else, you should add a unique index to that column in the movies table.
You should ultimately drop the title column from the actors table. Otherwise you'll either have multiple rows for the same actor name (redundant) or only one movie per actor (unrealistic).
For the first method you mentioned, you actually can first create the movie_actor table and then populate the existing data:
INSERT INTO movie_actor (movieid, actorid) SELECT movieid, actorid FROM movies INNER JOIN actors ON actors.title=movies.title;
For the second, you can use a trigger:
delimiter //
CREATE TRIGGER add_actor
AFTER INSERT ON actors
FOR EACH ROW BEGIN
SET #movieid = (SELECT movieid FROM movies WHERE title=NEW.title);
IF #movieid IS NOT NULL THEN
INSERT INTO movie_actor (movieid, actorid) VALUES (#movieid, NEW.actorid);
END IF;
END;
//
delimiter ;
I'd suggest option 1 followed by having whatever form you're using to populate these tables to populate the movie_actor table independently (e.g. after adding an actor, you can set whatever movies he/she was in, merely adding a mapping to the movie_actor table). Then if you want to get a list of movies for an actor you can just
SELECT title FROM movie_actor
INNER JOIN movies ON movies.movieid=movie_actor.movieid
WHERE actorid=????
I have two tables. "users" and "movies". Users table consists of "id"(Auto increment), "name" and "password" columns. There are 2 usernames stored right now. In movies table there are 'title' and 'year' columns. The PHP script allows each user to watch and add new movies to their list. How do I link or make the parent-child relationship or whatever is needed to make it happen in MySQL? Oh, and I also use Adminer. Right now when I log in one user I still see the same movies that I've added with the other user.
If you are stuck with using just two tables as stated in a comment, you have to redesign the Movies table to include a column UserID which identifies which user created that entry. Then you can filter the data so that a user only sees information about the movies they added to the list.
This isn't a good design — the answer by Jeremy Smyth suggesting an extra table to relate movies to users is much more sensible, but you've indicated that isn't allowed. The reason it isn't a good design is that you're going to end up with lots of rows indicating that the same movie was released in the same year, each row entered by a different user, so there is unnecessary repetition. There's also more chance for error; you'll get entries for 'Gone With The Wind' 1938, and 'Gone With The Wind' 1939, and 'Gone With The Wind' 1940 when there should only be one year (1939, as it happens).
Can you please be more specific about what I have to do ...
In the two-tables-only system, you would create the Movies table like this:
CREATE TABLE Movies
(
Title VARCHAR(32) NOT NULL,
Year INTEGER NOT NULL,
UserID INTEGER NOT NULL REFERENCES Users(ID),
PRIMARY KEY(Title, Year, UserID)
);
When you insert a record into this table, you record the ID of the user who did the insertion, so you can query who created which movie records.
If you are actually going to reference this table from elsewhere in the database, you might well add an ID column here, but if there are more tables, then you'd drop the UserID column from this table and create a relationship table:
CREATE TABLE Movies
(
ID INTEGER AUTOINCREMENT PRIMARY KEY,
Title VARCHAR(32) NOT NULL,
Year INTEGER NOT NULL,
UNIQUE(Title, Year)
);
CREATE TABLE Users_Movies
(
MovieID INTEGER NOT NULL REFERENCES Movies(ID),
UserID INTEGER NOT NULL REFERENCES Users(ID),
PRIMARY KEY(MovieID, UserID)
);
Now you can have one record for 'Gone With The Wind' 1939, which might have ID number 207, and twenty different people might list MovieID 207 as one of their movies with 20 simple records in the Users_Movies table.
You will need to create a "many-to-many" relationship between your two tables.
To do this:
First, create an ID column in the Movies table to uniquely identify each one
Then, create another table called user_movies (or "watched" or something useful), that contains the user ID, the movie ID, and any other information you wish to add such as date watched or rating (number of "stars") etc.
Then, whenever a user watches a movie, add a record to the user_movies table to mark the fact that they've done it.
It should be many-to-many, because each user can watch several movies, but each movie can be watched by several users. A "parent-child" relationship isn't appropriate in this case, being a one-to-many relationship.
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
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.