Nested Query count ID if they're related - mysql

I've got a project where I need to get the total number of directors and films.
It should be 6 directors and 12 films in total.
However, I have 8 directors and 12 films.
CREATE TABLE `director` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `director` VALUES
(1,'Roman Polanski'),
(2,'George Lucas'),
(3,'Steven Spielberg'),
(4,'Sam Mendes'),
(5,'Sofia Coppola'),
(6,'Michael Bay'),
(7,'Justin Lin'),
(8,'Francis Coppola');
CREATE TABLE `film` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`director_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `film` VALUES
(1,'Saw',7),
(2,'Jaw',3),
(3,'The Pianist',1),
(4,'1917',4),
(5,'Fast and Furious',7),
(6,'Star Wars',2),
(7,'ET',3),
(8,'James bond',4),
(9,'Lost in Translation',5),
(10,'Close Encounter of the Third Kind',3),
(11,'Blood',4),
(12,'Somewhere',5);
And this is the query I used:
SELECT (
SELECT COUNT(*)
FROM director
) AS directors,
(
SELECT COUNT(*)
FROM film
) AS films
FROM dual
I'm wondering if there's a way to count the director id only if it's related to the film's id?

Just count the distinct director IDs in the film table:
select
count(*) as films,
count(distinct director_id) as directors
from film
There is no need to touch the director table at all. But as an exercise you could do the following:
select count(*) as directors
from director d
where exists (
select *
from film f
where f.director_id = d.id
)
Which will count directors who have ever directed a film.
See demo on db-fiddle.com

Related

MySQL get average of top 16 from sub query [duplicate]

This question already has answers here:
Get top n records for each group of grouped results
(12 answers)
MySQL select top X records for each individual in table
(1 answer)
Closed 3 years ago.
I have two tables Teams and Players. A Team can have an unlimited number of Players and a Player can only belong to one team.
Each Player on a team has a wage.
I would like to get the average wage of the top 16 players at each team (or the less if there are less than 16 players).
Here is an example schema:
CREATE TABLE `teams` (
`id` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`aw16 DECIMAL(10,2) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `players` (
`id` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`team_id` INT(10) UNSIGNED NOT NULL,
`wage` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
I can get the top 16 average for one team at a time quite easily like so:
SELECT teams.name, AVG(players.wage)
FROM teams
INNER JOIN (
SELECT wage, team_id
FROM players
WHERE team_id = 1
ORDER BY wage DESC
LIMIT 16
) players
ON team_id = teams.id
GROUP BY teams.id
But I can't figure out how to do it for all Teams in one query so I can wind up with the "Team ID" and the "Top 16 Average" in two columns.
What's more I actually want to do an update and fill the aw16 field in the Teams table with the calculation for each team, but that seems even more problematic.
try this out
SELECT teams.name, AVG(players.wage)
FROM teams
INNER JOIN (
select wage, team_id
from players
where (
select count(*) from players as p
where p.team_id = players.team_id and p.wage >= players.wage
) <= 16
) players
ON team_id = teams.id
GROUP BY teams.id

Trouble with JOINS in mysql

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

SELECT with INNER JOIN, GROUP BY by and WHERE

I have a 3 MySQL tables about movies. First one is movie, second is actor and last one is movie_actor_mapping.
CREATE TABLE `movie` (
`movie_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(50) DEFAULT NULL,
`year` varchar(9) DEFAULT NULL,
`rating` float(2,1) DEFAULT NULL,
`runtime` varchar(6) DEFAULT NULL,
`plot` varchar(1500) DEFAULT NULL,
PRIMARY KEY (`movie_id`),
UNIQUE KEY `title` (`title`)
)
CREATE TABLE `actor` (
`actor_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(40) DEFAULT NULL,
PRIMARY KEY (`actor_id`),
UNIQUE KEY `name_en` (`name`)
)
CREATE TABLE `movie_actor_mapping` (
`movie_actor_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`movie_id` int(10) unsigned DEFAULT NULL,
`actor_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`movie_actor_id`),
UNIQUE KEY `movie_actor_id` (`movie_actor_id`)
)
Some movies has NULL in rating and when I do SELECT I have to select all movies which has rating and order them by rating. My SELECT looks like:
SELECT *, group_concat(a.name separator ', ') as actors
FROM movie m INNER JOIN movie_actor_mapping ma
ON m.movie_id=ma.movie_id
INNER JOIN actor a
ON a.actor_id=ta.actor_id
GROUP BY m.movie_id;
Also I wrote a select and order SELECT * FROM movie WHERE rating is not null ORDER BY rating DESC; but I don't understand how to split these queries. I know that if I will not have GROUP BY - I can write my second query after ON but how to do that using GROUP BY?
UPD:
I add example data from my tables. So, for movie it's:
1 | "American Horror Story" | "2011–" | 8.2 | "60 min" | "Both physical..."
A data from actor table:
1 | Evan Rachel Wood
From movie_actor_mapping:
1 | 21 | 1
Maybe I don't understand the question, because it seems too simple, but this query:
SELECT m.*, group_concat(a.name separator ', ') as actors
FROM movie m
INNER JOIN movie_actor_mapping ma ON m.movie_id = ma.movie_id
INNER JOIN actor a ON a.actor_id = ma.actor_id
WHERE m.rating IS NOT NULL
GROUP BY m.movie_id
ORDER BY m.rating DESC
...is selecting movies with rating, groups actors and orders them by rating
Try:
SELECT *, group_concat(a.name order by rating desc separator ', ' ) as actors
FROM movie m INNER JOIN movie_actor_mapping ma
ON m.movie_id=ma.movie_id
INNER JOIN actor a
ON a.actor_id=ta.actor_id
WHERE rating is not null
GROUP BY m.movie_id;
When you use GROUP BY, you need to have some aggregation action on those returned values that are not used for grouping (for instance, COUNT, MAX, MIN, etc.).
If what you want is to get the list of movies where all records of a specific movie are together, you can use the ORDER BY clause. In your case, it could be movie_id.

MySQL - Getting data from separate tables and sorting by their dates

I have two separate tables, each containing items that have a 'date' field. I'm trying to figure out how to list all items from both tables together (where year_id = 3) and sort them by date.
Here is the code for the "important_dates" table:
CREATE TABLE important_dates (
id int(11) NOT NULL AUTO_INCREMENT,
year_id tinyint(2) NOT NULL,
title varchar(60) NOT NULL,
date date NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and
INSERT INTO important_dates (id, year_id, title, date)
VALUES
(1,3,'Cannes Film Festival','2015-05-24'),
(2,3,'Toronto Film Festival','2015-09-10'),
(3,3,'Venice Film Festival','2015-09-12'),
(4,3,'People\'s Choice Awards','2016-01-06'),
(5,3,'Golden Globe Awards','2016-01-10'),
(6,3,'Independent Spirit Awards','2016-02-20'),
(7,3,'Razzies','2016-02-20'),
(8,3,'Oscars','2016-02-21');
Here is the code for the "movies" table:
CREATE TABLE movies (
id int(11) NOT NULL AUTO_INCREMENT,
year_id int(2) NOT NULL,
title varchar(100) NOT NULL,
release_date date NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and
INSERT INTO movies (id, year_id, title, release_date)
VALUES
(1,3,'The Hunger Games: Catching Fire','2013-11-22'),
(2,3,'Man of Steel','2013-06-14'),
(3,1,'Star Trek Into Darkness','2013-05-16'),
(4,3,'The Great Gatsby','2013-05-10');
The desired output is something like this:
2013-05-10: The Great Gatsby
2013-06-14: Man of Steel
2013-11-22: The Hunger Games: Catching Fire
2015-05-24: Cannes Film Festival
2015-09-10: Toronto Film Festival
2015-09-12: Venice Film Festival
2016-01-06: People's Choice Awards
2016-01-10: Golden Globe Awards
2016-02-20: Independent Spirit Awards
2016-02-20: Razzies
2016-02-21: Oscars
I've tried using joins and subqueries and I just can't figure it out. and I know it's probably simple. Thanks for any help on this.
Suggest you crete a mysql view to combine two table records:
DROP VIEW IF EXISTS view_movies;
CREATE OR REPLACE VIEW view_movies AS
SELECT id,year_id,title,`date` from important_dates
union all
SELECT id,year_id,title,release_date from movies
then select you wanted results from view_movies
select * from view_movies where year_id = 3 order by `date` asc
Hope this can help you !
You can use UNION
SELECT *
FROM
(SELECT date AS DATE, title AS TITLE
FROM important_date
WHERE year_id=3
UNION
SELECT release_date AS DATE, title AS TITLE
FROM movies
WHERE year_id=3
) AS result
ORDER BY DATE

Select only the last inserted item related to another registry

I modeled a small database for easier explanation:
CREATE TABLE bands (
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(120) NULL,
PRIMARY KEY(id)
)
TYPE=InnoDB;
CREATE TABLE albums (
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
band_id INTEGER UNSIGNED NOT NULL,
album_name VARCHAR(120) NULL,
rating INTEGER UNSIGNED NULL,
insertion_date TIMESTAMP NULL,
PRIMARY KEY(id),
INDEX albums_FKIndex1(band_id),
FOREIGN KEY(band_id)
REFERENCES bands(id)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
TYPE=InnoDB;
Now, pretending that we already have some bands and many albums registered in their respective tables, I want to select ONLY the last inserted album from each registered band.
PS: I have to use the "album.insertion_date" field to determine which album is the last inserted.
Try joining the two tables and filtering by insertion_date and band:
SELECT al.*
FROM albums al
INNER JOIN bands b ON al.band_id=b.id
WHERE al.insertion_date=(
SELECT max(insertion_date)
FROM albums
WHERE band_id=b.id
)
Try this one:
select b.name, a.album_name, a.isertion_date
from bands b, albums a
where a.band_id = b.id
and a.insertion_date = (select max(a1.insertion_date) from albums a1 where a1.band_id = b.id)
Considering that you have the albums' ids to be AUTO_INCREMENT and the possibility for the insertion_date to be NULL(as it is the default value), using insertion_date to determine the results is not the smartest thing to do but ... there you go:
SELECT DISTINCT band, last_album, insertion_date
FROM (
SELECT bands.name AS band, albums.album_name AS last_album, albums.insertion_date
FROM bands
JOIN albums ON bands.id=albums.band_id
ORDER BY albums.insertion_date DESC
) t1
GROUP BY band;