How to write query that join the 2 tables? - mysql

Using mysql. Database sakila.
Having two tables films and language. Film table has two foreign keys language_id and original_language_id that connects to language_id primary key in language.
So what I want is to learn how to get film, it's language and original language from such structure.
enter image description here
The query will display film in its language, without original.
SELECT
film.title, film.description, film.release_year, language.*
FROM
film
INNER JOIN
language ON film.language_id = language.language_id;

If I understood correctly, you want to select the films having language other than original language. I think a where clause will serve the purpose.
SELECT
film.title, film.description, film.release_year, language.*
FROM
film INNER JOIN language
ON film.language_id = language.language_id;
where film.language_id <> film.original_language_id
Or, If you just want to display language information for both the language you can follow one of below query (using subquery):
SELECT film.title, film.description, film.release_year,
(select name from language l where l.language_id=film.language_id) language_name,
(select name from language l where l.language_id=film.original_language_id) original_language_name
FROM film

Maybe you can try this
SELECT a.title, a.description, a.release_year, b.language_id, b.name, b.last_update
FROM
film a
INNER JOIN
language b ON a.language_id = b.language_id;

Related

MariaDB Query with multiple joins

In this database
https://www.databasestar.com/sample-database-movies/
I would like to make the following query: "List the name and genre of all the actors in the film Brazil".
I make this query:
USE movies;
SELECT DISTINCT p.person_name AS 'Nombre', g.gender AS 'Sexo' FROM movie m
JOIN movie_crew mc ON m.movie_id = mc.movie_id
JOIN department d ON mc.department_id = d.department_id
JOIN movie_cast mc2 ON m.movie_id = mc2.movie_id
JOIN person p ON mc2.person_id = p.person_id
JOIN gender g ON mc2.gender_id = g.gender_id
WHERE m.title = 'Brazil' AND d.department_name = 'Actors';
But no results appear and I don't understand where is my mistake.
Thanks.
I recommend you simplify the schema somewhat.
Just use simple strings for genre, language_role, keyword, gender, person_name
Use iso_code in place of country_id
Perhaps simple abbreviations for department and company
These do need normalizing (as you have don): person, movie, company, but mostly because there is other stuff in those entities.
That is, get rid of most of the tables in the leftmost and rightmost columns.
Once you have made that change, the error may mysteriously go away. (And, when you get more data, the queries will run faster. This does assume you have suitable indexes.)

MySQL JOIN one of the rows from second table

I have 2 tables: one for the restaurants containing general information, and the other - for it's description translations. The second table has such columns:
restaurant_id, description, language
The client application makes request for the list of restaurants, and passes the language it wants the result for. So now I need to JOIN those 2 tables. Everything would be easy, if each restaurant had description in each of available languages, but it does not. Some restaurants are missing descriptions in some languages.
So in case if the description is missing in selected language, I should return a description in default language (let it be eng for example).
So the question is how can I JOIN the tables the way that if the description in selected language is available - join with it, otherwise - join with eng?
What you can do is left join onto your translations table with the chosen language and also inner join onto translations again with the default language.
Then you can use COALESCE to chose the first, non-null value. For example
SELECT r.name, COALESCE(t.description, t_default.description) as description
FROM restaurant r
LEFT JOIN translation t ON r.id = t.restaurant_id
AND t.lang = 'fr' -- the chosen language
INNER JOIN translation t_default ON r.id = t_default.restaurant_id
AND t_default.lang = 'en' -- the default language
Demo ~ http://sqlfiddle.com/#!9/aa68c0/1
I've used an INNER JOIN for the default language to ensure there's a value to display. If you're fine with a possible NULL result, change it to a LEFT JOIN.
One more solution is to use temporary table to select IDs of the restaurants which have translation, and then using UNION to combine the restaurants with translation + all default restaurants excluding restaurant IDs having translations:
Create temporary table with IDs:
CREATE TEMPORARY TABLE IF NOT EXISTS existing_ids AS (SELECT r.id FROM restaurant r JOIN translation t ON r.id = t.restaurant_id WHERE t.lang = 'fr');
Select rows having translation:
SELECT r.name, t.description FROM restaurant r JOIN translation t ON r.id = t.restaurant_id WHERE t.lang = 'fr'
Union with rows with default translation excluding IDs from the temporary table:
UNION
SELECT r.name, t.description FROM restaurant r JOIN translation t ON r.id = t.restaurant_id WHERE t.lang = 'en' AND id not in (SELECT id from existing_ids)
Demo:
http://sqlfiddle.com/#!9/d3e66dc/1

Getting an Odd Syntax Error With SQL Query

I'm writing what should be a fairly straightforward SQL query for a modification of the IMDB database; it's supposed to return a list of all films that are categorized as BOTH horror and comedy, which I've done by creating a list of horror, a list of comedy, and then deleting everything from one that's not in the other. The query is as follows:
WITH
table_left AS (SELECT primary_names.name AS name, year, genre, title_id
FROM titles NATURAL JOIN primary_names NATURAL JOIN title_genres WHERE genre = 'Horror'),
table_right AS (SELECT primary_names.name AS name, year, genre, title_id
FROM titles NATURAL JOIN primary_names NATURAL JOIN title_genres WHERE genre = 'Comedy')
DELETE FROM table_right WHERE (title_id NOT IN (SELECT table_left.title_id))
SELECT name, year FROM table_right;
However, this generates an "ERROR: syntax error at or near 'SELECT'" on the last line of the query. I'm fairly new to SQL, but have gone over the syntax multiple times and checked some guides and I just can't understand what's going wrong. There shouldn't be a comma after the DELETE FROM statement, I don't think I've got a comma in any inappropriate places...it may be staring me in the face, but I'm at a loss, and would love to hear any suggestions.
When you use the WITH syntax, you can declare multiple table expressions, but then you can follow it with just one SQL query.
But you have two — a DELETE followed by a SELECT, with no statement terminator between the two statements. This doesn't match any syntax rule of SQL.
I could comment that another way to achieve what you want, listing films that are in two categories, is to do a self-join.
SELECT p.name, t.year, t.title_id
FROM titles AS t
INNER JOIN title_genres AS g1 ON t.title_id = g1.title_id AND g1.genre = 'Horror'
INNER JOIN title_genres AS g2 ON t.title_id = g2.title_id AND g2.genre = 'Comedy'
INNER JOIN primary_names AS p ON t.title_id = p.title_id
You really need to learn how to use JOIN if you're coding with SQL. Not doing so is like using another language like Java or Ruby without understanding loops. I don't mean joins are like loops, just that joins are a foundational part of the SQL language, and you need to know how to use them.

MySQL Join with looped reference query

I have a slightly complex table structure that I'm trying to query for a search function, but my queries keep timing out. Basically, it's a book search, and I'm focusing on the subject portion of that search.
The subjects table is simple (id and title), but there's a link table that refers it back to itself called subjects_subjects, which complicates things.
**subjects_subjects**
id (key)
subject_id (reference to subjects table)
see_subject_id (another reference to subjects table)
The reason for the looping reference is to catch subjects that don't contain any books, but point to subjects that do. For example, there's no books under the 'Travel' subject, so that subject has a link to 'Explorers' and 'Voyages' that do contain books. The point is to make searching easier.
So what I'm trying to do is allow the user to search for 'Travel', but return results from 'Explorers' and 'Voyages'. Here's my query that times out:
SELECT
BK.id,
BK.title
FROM
books BK
LEFT OUTER JOIN
books_subjects BS
ON BS.book_id = BK.id
WHERE
BS.subject_id IN (1639,3173)
OR BS.subject_id IN
(
SELECT
SS.see_subject_id
FROM
subjects_subjects SS
WHERE
SS.subject_id IN (1639,3173)
)
GROUP BY
BK.books_id
Extra info: There are 17000 books and over 3000 subjects in the database, with roughly 84000 book/subject references.
Can anyone help me figure out where am I going wrong here?
You're doing two things that MySQL optimizes poorly:
OR in the WHERE clause.
IN (SELECT ...)
Instead of OR, use two queries that you combine with OR. And instead of IN (SELECT ...) use a JOIN.
Also, you shouldn't use LEFT JOIN if you don't need to return rows from the first table with no matches in the second table, use INNER JOIN.
SELECT b.id, b.title
FROM books AS b
JOIN books_subjects AS bs ON bs.book_id = b.id
WHERE bs.subject_id IN (1639, 3173)
UNION
SELECT books AS b
JOIN books_subjects AS bs ON bs.book_id = b.id
JOIN subjects_subjects AS ss ON bs.subject_id = ss.see_subject_id
WHERE ss.subject_id IN (1639, 3173)

SQL Query INTERSECTS - Relational Algebra

I am trying to convert the following 2 relational algebra into standard english but I am having trouble understand what exactly the INTERSECTS does
I know that INTERSECT finds the values that occur in both select statements
I have managed to find its SQL query, but I just can't figure out what it asks in plain english
Would anyone be able to help?
Relational Algebra:
Πstudent_name(σcourse id=“CS1850“(student Natural Join enrolled)) ∩
Πstudent_name(σcourse id=“CS1840“(student Natural Join enrolled))
SQL:
SELECT student_name FROM student NATURAL JOIN enrolled WHERE
course_id='CS1850' INTERSECT SELECT student_name FROM student
NATURAL JOIN enrolled where student_name='CS1840'
Second Expression:
Πstudent_name(σe1.student
id=e2.student_id∧e1.course_id<>e2.course_id(student natural join
(ρe1(enrolled) × ρe2(enrolled))))
SELECT student_name FROM student NATURAL JOIN enrolled e1 NATURAL JOIN
e2 WHERE e1.student_id = e2.student_id
First, don't use NATURAL JOIN. It is an error waiting to happen. It matches tables based on the names of columns in common. It doesn't even use properly declared foreign key relationships. Instead, use USING or ON to be explicit about the columns used for joining.
Second, you don't need INTERSECT. There are two typical methods that use GROUP BY or JOIN.
In English, the query gets the students that are enrolled in both classes.
SELECT s.student_name
FROM student s JOIN
enrolled e
USING (student_id) -- or whatever
WHERE e.course_id IN ('CS1850', 'CS1840')
GROUP BY s.student_name
HAVING COUNT(*) = 2;
Note: This assumes that two students do not have the same name.
An alternative just uses JOIN:
SELECT s.student_name
FROM student s JOIN
enrolled e1
USING (student_id) JOIN
enrolled e2
USING (student_id)
WHERE e1.course_id = 'CS1850' AND
e2.course_id = 'CS1840';
If the underlying tables do not have duplicates, then this doesn't need a GROUP BY or DISTINCT.