I'm trying to create a view in MySQL to include from 3 different tables.
CREATE TABLE ACTOR (
ACTOR_ID DECIMAL (2,0) PRIMARY KEY NOT NULL,
ACTOR_FIRST CHAR(25),
ACTOR_LAST CHAR(30),
DOB DATE
);
CREATE TABLE DIRECTOR (
DIRECTOR_ID DECIMAL(2,0) PRIMARY KEY NOT NULL,
DIRECTOR_FIRST CHAR(25),
DIRECTOR_LAST CHAR(30)
);
CREATE TABLE FILM (
FILM_ID DECIMAL(2,0) PRIMARY KEY NOT NULL,
TITLE CHAR(50),
RELEASE_DATE DATE,
DIRECTOR_ID DECIMAL(2,0),
GENRE_ID CHAR(10),
PRODUCTION_ID CHAR(3)
);
The VIEW I'm trying to create:
create view film_production as
select
title,
actor_first,
actor_last,
director_first,
director_last,
Production_id,
release_date
from film,
actor,
director
;
This gives me like 192 results. But I only have 3 actors, with 8 movies with 8 directors, and 6 production_id's. Another thing to note is 1 movie has 2 of the 3 actors in it, so I should have at least 9 movies that show not 192. I don't know what I'm doing wrong. I just cant figure this out. I'm thinking maybe a join or some kind.
Yes, your view should use joins.
BUT, it looks like you are missing a table, something like film_actor.
Using the missing table, and assuming you are trying to get the cast and directors of each movie it would be
SELECT
FILM.*
,ACTOR_FIRST + ' ' + ACTOR_LAST AS actor
,DIRECTOR_FIRST + ' ' + DIRECTOR_LAST AS director
FROM FILM
INNER JOIN FILM_ACTOR fa ON fa.FILM_ID = FILM.FILM_ID
INNER JOIN ACTOR ON ACTOR.ACTOR_ID = FILM_ACTOR.ACTOR_ID
INNER JOIN DIRECTOR d ON d.DIRECTOR_ID = FILM.DIRECTOR_ID
Like I mentioned, you are missing a table that would hold multiple actors and associate them to one movie: a one to many relationship.
Have you thought of adding referential keys between actor and film, and director and film tables?
Actor
CREATE TABLE ACTOR (
ID INT PRIMARY KEY NOT NULL,
FIRSTNAME VARCHAR(25),
LASTNAME VARCHAR(30),
DOB DATE
);
Director
CREATE TABLE DIRECTOR (
ID INT PRIMARY KEY NOT NULL,
FIRSTNAME VARCHAR(25),
LASTNAME VARCHAR(30)
);
Film with connections to actor and director
CREATE TABLE FILM (
FILM_ID INT PRIMARY KEY NOT NULL,
TITLE VARCHAR(50),
RELEASE_DATE DATE,
DIRECTOR_ID INT,
GENRE_ID INT,
PRODUCTION_ID INT,
ACTOR_ID INT,
CONSTRAINT FK_FILM_DIRECTOR_ID FOREIGN KEY (DIRECTOR_ID)
REFERENCES DIRECTOR(ID),
CONSTRAINT FK_FILM_ACTOR_ID FOREIGN KEY (ACTOR_ID)
REFERENCES ACTOR(ID)
);
View combining the 3 tables
create view film_production as
select
title,
a.firstname as actor_firstname,
a.lastname as actor_lastname,
d.firstname as director_firstname,
d.lastname as directory_lastname,
Production_id,
release_date
from film f
left join actor a on f.actor_id = a.id
left join director d on f.director_id = d.id;
Example: http://sqlfiddle.com/#!9/9fe1e
Note that I have used INT instead of DECIMAL for ID fields and VARCHAR instead of CHAR fields. This may help in allocating the right space for most general purpose uses.
Related
I have a basic problem about create a query for Find the Playlists without any track of the genres “Latin”, “Rock” or “Pop”. I am really struggling with Joins some exercises I can do well but with this I can figure out.
I tried This:
SELECT p.PlaylistId as Playlist, p.Name
FROM Playlist p INNER JOIN PlaylistTrack pt ON p.PlaylistId = pt.PlaylistId
INNER JOIN Track t ON pt.TrackId = t.TrackId
JOIN Genre g ON g.GenreId = t.GenreId
WHERE g.Name <> "Latin " AND "Rock" AND "Pop"
My Output are returning 1 value: AC/DC, and null values when I use LEFT JOIN.
This is my DDL:
CREATE TABLE Genre (GenreId int PRIMARY KEY, `Name` CHAR(255) );
CREATE TABLE MediaType ( MediaTypeId int PRIMARY KEY, `Name` CHAR(30) );
CREATE TABLE Artist(ArtistId INT PRIMARY KEY, `Name` CHAR(255) ); -- LONG CHAR????
CREATE TABLE Album(AlbumId INT PRIMARY KEY, Title CHAR(120), ArtistId INT );
CREATE TABLE Track( TrackId int PRIMARY KEY, `Name` CHAR(255), AlbumId INT,
MediaTypeId INT, GenreId INT, Composer CHAR(220), Milliseconds int, Bytes INT, UnitPrice decimal(8,2)); -- UnitPrice number
CREATE TABLE Playlist(PlaylistId int PRIMARY KEY, `Name` CHAR(30));
If you are more interested and want to test this database that I build check this link, is a little dirty and need to be improve but commenting some rows will work.
As I Said: My Output are returning 1 value: AC/DC, and null values when I use LEFT JOIN.
This is the expected value:
PlaylistId
Name
2,
Movies
5
TV Shows
6
Audiobooks
7
Audiobooks
8
Movies
9
Music Videos
10
TV Shows
11
Classical
12
Classical 101 - Deep Cuts
13
Classical 101 - Next Step
14
Classical 101 - The Basics
15
On-The-Go 1
I thought that this question was really easy. I dont understand why I can't figure out, can someone help me?
SELECT *
FROM Playlist
WHERE NOT EXISTS ( SELECT NULL
FROM PlaylistTrack
INNER JOIN Track USING (TrackId)
INNER JOIN Genre USING (GenreId)
WHERE Playlist.PlaylistId = PlaylistTrack.PlaylistId
AND Genre.Name IN ('Latin', 'Rock', 'Pop') )
I'm trying to create MySQL queries to answer some questions after creating the following database:
create table teachers (
teacher_id int primary key auto_increment,
name varchar(50),
surname varchar(50),
dob date,
employment_day date
);
create table students (
student_id int primary key auto_increment,
name varchar(50),
surname varchar(50),
dob date,
no_of_lessons_left int
);
create table aircrafts (
aircraft_id int primary key auto_increment,
manufacturer varchar(50),
serial_number varchar(50), -- or int?
cycles int
);
create table schools (
school_id int primary key auto_increment,
address varchar(50),
opening_date date
);
create table lessons (
lesson_id int primary key auto_increment,
teacher_id int not null,
student_id int not null,
aircraft_id int not null,
school_id int not null,
lesson_date date,
constraint lessons_teacher foreign key(teacher_id) references teachers(teacher_id),
constraint lessons_student foreign key(student_id) references students(student_id),
constraint lessons_aircraft foreign key(aircraft_id) references aircrafts(aircraft_id),
constraint lessons_school foreign key(school_id) references schools(school_id)
);
Below some queries, I tried for the questions using double join:
Questions are :
• How many aircraft are there per each school at some point in time?
I can't figure out how to answer these conditions " per each school at some point of time"
• How many students are attending one particular school?
select count(*) from students s
inner join lessons l on l.student_id = s.student_id
inner join schools sc sc.teacher_id= l.teacher_id
where sc.name = "PilotingSchoolName";
• How many students does each teacher have at some particular moment
select count(*) from students s
inner join lessons l on l.student_id = s.student_id
inner join schools sc sc sc.teacher_id= l.teacher_id;
However, I'm missing the condition " at some particular moment " in the query I wrote.
You have a lessons.lesson_date column, and can limit to one point in time with something like AND lesson_date = '2019-12-08' or a date range with AND lesson_date BETWEEN '2018-01-01' AND '2019-12-08'. If the requirements did not ask you to find a specific exact date, it sounds like they'd just like you to be able to demonstrate how to use lesson_date in WHERE.
In your response to "how many students does each teacher have" problem, you are missing a crucial GROUP BY clause. The query you have now is close, but will instead show the total number of enrolled students. Grouping by teachers.name will complete the query (along with a lesson_date constraint)
select
t.name,
-- count each student only once per teacher
count(DISTINCT s.student_id) AS
from teachers t
-- left join so teachers with no enrolled
-- students will list as zero
left join lessons l on t.teacher_id = l.teacher_id
left join students s ON l.student_id = s.student_id
WHERE
-- A specific date
l.lesson_date = '2019-12-08'
GROUP BY t.name
To get the aircrafts per school at a particular time, the query is very similar, but with different joins.
select
-- List all schools, and count of aircraft per school
s.school_id,
count(DISTINCT l.aircraft_id)
from
schools s
-- left join, so that schools with zero current aircraft
-- are include in the results
left join lessons l ON l.school_id = s.school_id
where
l.lesson_date = '2019-12-08'
-- GROUP BY necessary to get the count per school
GROUP BY s.school_id
I was working in mySQL and made a fake database for reviews, reviewers and tv series. So I made 3 different tables, one for reviewers, one for reviews and one for the series.
CREATE TABLE reviewers
(
id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(150) NOT NULL
);
CREATE TABLE series
(
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(100) NOT NULL,
released_year YEAR(4),
genre VARCHAR(50)
);
CREATE TABLE reviews(
id INT AUTO_INCREMENT PRIMARY KEY,
rating DECIMAL(2,1),
series_id INT,
reviewer_id INT,
FOREIGN KEY(series_id) REFERENCES series(id),
FOREIGN KEY(reviewer_id) REFERENCES reviewers(id)
);
The thing that I wanted to ask is, how can I get the highest rating from each reviewer and in which show they gave it?
UPDATE
I came up with this code
SELECT first_name,last_name,title, a.series_id,a.rating FROM
( SELECT series_id,MAX(rating) AS max FROM reviews
GROUP BY series_id ) AS b
INNER JOIN reviews AS a
ON a.series_id=b.series_id AND a.rating=b.max
INNER JOIN reviewers
ON reviewers.id=a.reviewer_id
INNER JOIN series
ON series.id=a.series_id
GROUP BY series_id;
which gives me the max rating in each series and who gave that rating
I need to show all fields on the most expensive car of each manufacturer.
The two tables being used are:
CREATE TABLE CARS
(
Vehicle_Identification_Number int(10) NOT NULL UNIQUE,
Manufacturers_ID int(5),
Owner_ID int(10),
Model varchar(25),
Manufaturer_Year int(4),
Mileage int(10),
Price int(10),
PRIMARY KEY (Vehicle_Identification_Number),
FOREIGN KEY (Manufacturers_ID) REFERENCES MANUFACTURERS (Manufacturers_ID),
FOREIGN KEY (Owner_ID) REFERENCES OWNERS (Owner_ID)
)
ENGINE= innodb;
CREATE TABLE MANUFACTURERS
(
Manufacturers_ID int(5) UNIQUE,
Name varchar(15) UNIQUE,
City varchar(30),
State char(2),
Zip char(5),
Phone char(10),
PRIMARY KEY (Manufacturers_ID)
)
ENGINE= innodb;
What I have working so far is:
SELECT *
FROM MANUFACTURERS
LEFT JOIN CARS
ON MANUFACTURERS.Manufacturers_ID = CARS.Manufacturers_ID
UNION
SELECT *
FROM MANUFACTURERS
RIGHT JOIN CARS
ON MANUFACTURERS.Manufacturers_ID = CARS.Manufacturers_ID
ORDER BY Price DESC;
Here is where I am stuck, everything I have tried left me with an error message. Any help would be appreciated.
I'm not sure what you mean by "no duplicates from a different field".
The highest price for each manufacturer is this set. (There might be more than one car at the highest price.)
select Manufacturers_ID, max(Price)
from cars
group by Manufacturers_ID;
Join on both columns in that set. (Second inner join, below.)
select MANUFACTURERS.*, CARS.*
from CARS
inner join MANUFACTURERS
on MANUFACTURERS.Manufacturers_ID = CARS.Manufacturers_ID
inner join (select Manufacturers_ID, max(Price) as Price
from cars
group by Manufacturers_ID) as MOST_EXPENSIVE
on CARS.Manufacturers_ID = MOST_EXPENSIVE.Manufacturers_ID
and CARS.Price = MOST_EXPENSIVE.Price;
I've got four tables: person, coach, player, games. I need to write an SQL SELECT statement that will return: my id, name, date of birth, join date, the name of the coach with whom I am registered, and the date, time and duration of the game.
The person table consists of: person id, name, date of birth, and some other unnecessary values.
The coach table consists of: coach id, and some other unnecessary values.
The player table consists of: player id, join date, joined with.
The game table consists of: coach id, player id, game date, game time, game duration.
The person table basically stores all the names and main details both of the coach and of the players. The tables are linked correctly.
I've tried various statements but I totally confused myself. The example is kind of lame, I had something else but not really sure how to go about it anymore.
e.g.
SELECT person_id, full_name, date_of_birth, join_date
FROM (person JOIN player ON player_id = person_id)
WHERE person_id='100' AND person_id, full_name
FROM (person JOIN coach ON coach_id = person_id);
These are the CREATE statements:
CREATE TABLE person (
person_id CHAR(10) NOT NULL,
full_name VARCHAR(54) NOT NULL,
date_of_birth DATE,
sex CHAR(1),
PRIMARY KEY (person_id)
) engine innodb;
CREATE TABLE coach (
coach_id CHAR(10) NOT NULL,
phone_no CHAR(10) NOT NULL,
hall_no CHAR(4) NOT NULL,
PRIMARY KEY (coach_id),
FOREIGN KEY (coach_id) REFERENCES person (person_id)
) engine innodb;
CREATE TABLE player (
player_id CHAR(10) NOT NULL,
join_date DATE NOT NULL,
joined_with CHAR(10),
PRIMARY KEY (player_id),
FOREIGN KEY (player_id) REFERENCES person (person_id),
FOREIGN KEY (joined_with) REFERENCES coach (coach_id)
) engine innodb;
CREATE TABLE game (
coach_id CHAR(10) NOT NULL,
player_id CHAR(10) NOT NULL,
game_date DATE NOT NULL,
game_time TIME NOT NULL,
game_duration INTEGER DEFAULT 10,
PRIMARY KEY (coach_id, player_id, game_date, game_time),
FOREIGN KEY (coach_id) REFERENCES coach (coach_id),
FOREIGN KEY (player_id) REFERENCES player (player_id)
) engine innodb;
Your SQL is WAY off. It looks like you're trying for the following just using several INNER JOINs:
SELECT p.person_id, p.full_name, p.date_of_birth, pl.join_date,
c.coach_id, p2.full_name as coach_name, g.*
FROM person p
JOIN player pl ON p.person_id = pl.player_id
JOIN game g ON p.person_id = g.player_id
JOIN coach c ON c.coach_id = g.coach_id
JOIN person p2 on c.coach_id= p2.person_id
WHERE p.person_id='1'
ORDER BY p.person_id, p.full_name
You won't need to rejoin on person a second time if you don't need the coach's name -- I just presumed that would be useful information.
SQL Fiddle Demo
I hope this helps.
SELECT person.person_id, person.full_name, person.date_of_birth, player.join_date
FROM person
INNER JOIN player
ON player.player_id = person.person_id
WHERE person.person_id = '100'