Reputation: 1
I am trying to create an sql query (postgresql) which does a full outer join between two tables. For demonstration purposes I will use two tables: movies and genre. Some movies do not have a genre assigned yet and some genres are not in the movie database
Movie table:
Movie | Genre_id | Length |
---|---|---|
Inception | 01 | 120 |
The shining | NULL | 120 |
Die hard | 01 | 90 |
Genre table:
name | id |
---|---|
Thriller | 01 |
Drama | 02 |
What I want is a list of genres and the number of movies in that genre. But, I only want to see movies longer than 90 minutes. So my thought process is I need a full outer join and a filter:
SELECT
COALESCE(genre.name,'No genre'),
COUNT(movies.name)
FROM movies
FULL OUTER JOIN genre ON genre.id = movies.genre_id
WHERE movies.length > 90
GROUP BY genre.name
However, this query gives me this output:
coalesce | count |
---|---|
No genre | 1 |
Thriller | 1 |
I know why it gives me this output, and that is because 'Drama' doesn't match to any of the movies so a filter applied to 'movies' will not return anything. I need to somehow filter the movies before applying the full outer join. I have found two solutions myself which are a CTE or an inner join with the filters:
SELECT
COALESCE(genre.name,'No genre'),
COUNT(movies.name)
FROM movies
INNER JOIN movies m2 ON movies.name = m2.name AND movies.length > 90
FULL OUTER JOIN genre ON genre.id = movies.genre_id
GROUP BY genre.name
My question is: is there another way to solve this, which preferably doesn't use a CTE or a 'hacky' solution as I used above? I also found a solution using a subquery here FULL OUTER JOIN value condition but Im not sure how to use this in my case
(SQL Fiddle: http://sqlfiddle.com/#!15/860151/3)
EDIT: I found a solution:
SELECT
COALESCE(genre.name,'No genre'),
COUNT(movies.name)
FROM (SELECT * FROM movies WHERE movies.length > 90) movies
FULL OUTER JOIN genre ON genre.id = movies.genre_id
GROUP BY genre.name
Upvotes: 0
Views: 282
Reputation: 962
Try this:
SELECT
COALESCE(genre.name,'No genre'),
COUNT(movies.name)
FROM movies
FULL OUTER JOIN genre ON genre.id = movies.genre_id
WHERE movies.length > 90 or genre_id is null
GROUP BY genre.name;
You only need to include your NULL values on genre_id column in movie tables.
Upvotes: 0