SQL Multiple MANY_TO_MANY relationships - sql

I have a three objects: City, Channel, Genre. Relations: City has many Channels and Genres, and Channel and Genres may are in several Cities. Channels has many Genres, and but Genre may has many Channels.
I designed next database:
tblChannel:
id,
name
tblGenre:
id,
name
tblCity:
id,
name
// City and Channel MANY_MANY
tblCityChannel:
id,
cityId,
channelId
// City and Genre MANY_MANY
tblCityGenre:
id,
cityId,
genreId
// Channel and Genre MANY_MANY
tblChannelGenre:
id,
channelId,
genreId
I am not sure that this correctly, who can specify my mistakes?
RESOLVE:
I redesigned my database by next:
tblChannel:
id,
name
tblGenre:
id,
name
tblCity:
id,
name
tblCityChannelGenre:
id,
cityId, // NOT NULL
channelId,
genreId
That layout solves next problems:
I may create entites separately (channel may not have genre, genre
may not have channels)
City may have list of channels,
which are not be defined by genre, and with genres conversely.

your model is correct if it is a real m:m relationship between all 3 entities. however in the real world it is unlikely. most likely you have a hierarchy (like a tree) where you only have 2 m:m relationships and the third one is implied or you have a relationship between 3 tables so you need a table with 3 col key (not 3 tables with 2 col keys). try to understand you data better and you'll see what the correct model is. again, it could be just fine...

Related

How to combine two databases?

I am asking myself how to best define a new database given two databases.
I have the following two databases
Author where I save information about authors i.e. Name, Birthyear, Country, Genre etc.
Book where I save information about the book i.e. AuthorName, ReleaseYear, Pages etc
How do I create a new database with the full information about all books and the author? I.e. a Book_Complete Database which includes Author.Name, ReleaseYear,Pages, Genre,ReleaseYear and Author.Birthyear, Author.Country?
Better to go for a single database and having 2 tables in it like
Author Table
AuthorId (PK)
Name
Birthyear
Country
Genre
Book Table
BookId (PK)
AuthorId (FK)
ReleaseYear
Pages
If you have two tables in a database you can combine them using JOIN. Here is SQLite tutorial on how to use JOIN.
https://www.sqlitetutorial.net/sqlite-join/
On the information you provided I assume you can you columns Name in table Author, and AuthorName in table Book. You can try something like this
SELECT
A.Name,
B.ReleaseYear,
B.Pages,
B.Genre,
B.ReleaseYear,
A.Birthyear,
A.Country
FROM
Author A
LEFT JOIN Book B
ON A.Name = B.AuthorName
Basically, I have these create these two tables on my app and want to store the combined version on a server. Or would you suggest another approach?
Yes we would. You should have one table per entity, i.e. one for the authors and one for the books. Thus you don't store data redundantly (e.g. the author's name or the book's title), which could otherwise lead to inconsistencies later. You can read up on database normalization here: https://en.wikipedia.org/wiki/Database_normalization or google it.
Now you must decide how to link the tables. One author can write multiple books. Can one book be written by multiple authors? Give both tables IDs you can work with (or find some natural unique key, like the ISBN for the book and maybe name + birth year for the author - the name only will probably not suffice and maybe it won't even when combined with the year).
If one book can only be written by one author, you have a 1:n relation (one book written by one author, one author writing multiple books).
author (author_id, name, birth_year, country, ...)
book (book_id, title, author_id, release_year, pages, ...)
If one book can have several authors, you have an m:n relation (one book written by multiple authors, one author writing multiple books).
author (author_id, name, birth_year, country, ...)
book (book_id, title, release_year, pages, ...)
book_author (book_id, author_id)
You can always join the tables, so as to get a combined result.

Storing list of strings values for each row in a table is bad practice and violates normal forms. What should I do?

I'm doing a hobby project of creating my own movie database with ratings, genres, release dates and what actors are linked to what movies (to in the future distinguise movies from actors search).
I have a table containing Movies with some attributes where one attribute at the moment should be actors included in that movie. I know I can't store a list of strings (names of actors) in a cell for each row (movie) in the table. But what is best practice here? Create another table with MovieActors and link what movies each are connected to? What if the actor is connected to more movies?
I'm running Microsoft SQL Server Management Studio in my own localhost database and have just set up the Movie table where I found out I might get this problem.
I expect to get a table containing movies, and in the future be able to search movies, find their attributes and find out what actors are connected to that movie. Also be able to filter movies depending on what actor I've chosen.
What you have is a many-to-many relationship. When building a relational database, this would consist of a Movie Table, an Actor Table. and then a "junction" or "join" table, which houses a foreign key to both Movie and Actor. You can then join using this "junction" table to get all actors who were in a specific movie, or vice versa, get all movies a specific actor was in, etc.
Example Diagram:
Table Movie Table ActorMovie Table Actor
MovieId | MovieName MovieId | ActorId ActorId | ActorName
1 jaws 1 1 1 Guy1
2 star wars 1 2 2 Guy2
2 1
As you suggested, the usual practice is to have an intermediate MovieActors table, which links what movies have which actors.
Like this:
Movie Actor
1 2
1 3
1 4
2 2
2 5
You'll link the IDs with their respective tables via foreign keys (FK).

Varray compare item in the collections

The a table of movies with attribute of directors and actors. The actor is a varray type of actor_type contain 5 actor. i want to retrieve the movie that actor is both director and actor.
i tried
select actors, title, director
from movie
where actors = director
it telling me inconsistent datatype
You didn’t provide the sample data so my understanding from your description is:
The director and actor attribute are in the movie table and the actor is displayed as Varray, which being called actor_type. Also, the actor Varray contains 5 actors in each movie.
The way to query Varray is different, you can use TABLE expression in FROM clause.
This website might help you
Database Object-Relational Developer's Guide:
https://docs.oracle.com/database/121/ADOBJ/adobjcol.htm#ADOBJ00204
Then, you have to loop through the actor list and use the EXISTS or IN operator to check if the director is inside the actor list instead of using actors=director
You didn't specify what datatype the director column is. You can do a convert on the join actor = convert(director).
But I highly recommend you don't do this.
The problem with joining on strings is it is very inconsistent and if this is your only option to join actor to director, you need to restructure your tables.
I advise you have a Person table which contains both actors and directors.
You then need a table for movies and have the director and actor as foreign keys.
If the movie can have more than one actor, for instance, you then need a link table between person and movie tables (Same with the director if you have more than one director)
Hope this helps.

SQL movie database diagram

Im working on a small school project where im creating a movie database in SQL. I've created the tables and was wondering if I will encounter any problems with the model i created.
Thanks in advance.
Current diagram
Edit:
Here is the new diagram
MovieDetails is bad design. You need one row in MovieDetails per actor, while the director will be the same, which is data duplication. Instead, the Movie table should have a foreign key referencing director, then a MovieActor table should represent the many to many relationship between movies and actors.
Technically, there's also no reason to have different tables for Directors and Actors since you have the same data in the tables. You could just as well have a Person table with both.
How about (I am only showing the relevant columns)
movie table
-----------
id
title
person
------
id
name
cast table
----------
movie_id
person_id
movie_role_id (actor, director, ...)
role_type table
----------------
id
name (actor, director, ...)
genres table
------------
id
name
movie_genres table
------------------
movie_id
genre_id
I would consider the following structure:
movie(id, title, year, rating, plot, length)
actor(id, first name, last name, nationality, birth_date)
director(id, first name, last name, nationality, birth_date)
movie_x_actor(movie_id, actor_id)
movie_x_director(movie_id, director_id)
This is, of course, just the simplest example.
You can, for instance add a movie_series table like:
movie_series(id, title)
movie_x_movie_series(movie_id, series_id, plot_order_number)
and, like #Juergen described, a movie usually belongs to more than one genre so:
genres(id, genre_name, genre_description)
movie_x_genres(movie_id, genre_id)
You should definitely take a look at one-to-many and many-to-many relationships between rows in tables.
Cheers

What is the normalized database form for these 3 tables?

So I have three tables and subsequently three models as well:
Company (table: companies)
Person (table: people)
Address (table: addresses)
How to connect these together, considering that each Person or Company can have multiple addressess, but since the addresses are in the same format I'd like to use one single 'addresses' table, so dealing/managin addresses can be done trough a single model?
Because this structure:
companies(id, name, ...)
people(id,name, ... )
addresses(id, foreign_id, foreign_model, ...)
Seems a bit out of place for me. basically this is the current sructure now. The 'foreign_model' field is a string which specifies which model the address belongs to (i.e. Company or Person).
All this under Cakephp, but I have many problems with this structure, what should I use instead?
how abt this:
companies(id, name, address_id,..)
people (id,name, address_id,... )
addresses(id,... )
Both companies and people point to the address table for their address.
Here you dont have to store any duplicate addresses if any
EDIT: If both companies and people can have many addresses
Then keep a mapping table
companies(id, name,..)
people (id,name, ... )
addresses(id,... )
Address_map(id,address_id,type)
Where type says whether its a company or a people
id --> either companyid or poepleid