SQL - Query Assistance [closed] - mysql

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm pretty new to SQL and I am working on an assignment that requires me to find what movies were created by a company with "films" in its name based off the IMDB database.
A diagram of this database can be viewed here:
http://i.imgur.com/kj8qVgF.png
This is the query I was working on.
SELECT t.title, t.id
FROM title t, movie_link m
JOIN movie_companies c ON (m.movie_id = c.movie_id)
JOIN company_name n USING (id)
WHERE n.name LIKE '%films%'

Your code does seem to be somewhat close to what you'll need, but there are some weird things there. First of all, the implicit join here title t, movie_link m is performing a cartesian product between those tables. This code should work:
SELECT DISTINCT t.id, t.title
FROM title t
INNER JOIN movie_companies mc
ON t.id = mc.movie_id
INNER JOIN company_name cn
ON mc.company_id = cn.id
WHERE cn.name LIKE '%films%'
There are several things that you need to take into account from that diagram to get the results that you want. For instance, since different companies can be the creator of the same movie (the diagram allows it), you'll need to use DISTINCT otherwise you might get duplicate results.

Seems like you are missing a join predicate for the join between title and movie_link tables.
I recommend you NOT mix the "comma" and the "JOIN keyword" syntax in a statement. That is, remove that comma between title and movie_link) and replace it with the keyword JOIN. And add a join predicate, if you're not wanting a cross join.
Also, the USING syntax in the join predicate is a little ambiguous for my taste. I recommend you explicitly specify which columns from which tables you want to match, like you did for the join to movie_companies table.
The query below isn't runnable. The ??? need to be replaced with appropriate identifiers and aliases:
SELECT t.title
, t.id
FROM title t
JOIN movie_link m ON m.??? = t.???
JOIN movie_companies c ON c.movie_id = m.movie_id
JOIN company_name n ON n.id = ???.???
WHERE n.name LIKE '%films%'

Related

how to join two tables when matching entry doesn't exist [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
I am having some trouble writing this SQL Query.
Basically, I have the following tables;
received_flight_files_table & uploaded_flight_files_table
And the following fields;
Processing_Month, IATA_Code, Airline, Received_Date, Uploaded_Date
I would like the query to produce something like the first attached screenshot.
The 2 date fields you can see are from different tables though.
The join can be done on the IATA_Code and Airline fields as both of these values should be the same in both tables.
Here are 2 examples of statements I have written which aren't quite right;
SELECT DISTINCT received_flight_files_table.Processing_Month, received_flight_files_table.IATA_Code, received_flight_files_table.Airline, received_flight_files_table.Received_Date, uploaded_flight_files_table.Uploaded_Date, published_flight_table.Published_Date
FROM ((received_flight_files_table
INNER JOIN uploaded_flight_files_table ON uploaded_flight_files_table.Processing_Month=received_flight_files_table.Processing_Month)
INNER JOIN published_flight_table ON published_flight_table.Published_Month=received_flight_files_table.Processing_Month
WHERE received_flight_files_table.Processing_Month = [enter MMMYY];`
SELECT DISTINCT received_flight_files_table.Processing_Month, received_flight_files_table.IATA_Code, received_flight_files_table.Airline, received_flight_files_table.Received_Date, uploaded_flight_files_table.Uploaded_Date
FROM (((received_flight_files_table
INNER JOIN uploaded_flight_files_table ON uploaded_flight_files_table.Processing_Month=received_flight_files_table.Processing_Month
INNER JOIN uploaded_flight_files_table ON uploaded_flight_files_table.IATA_Code=received_flight_files_table.IATA_Code
INNER JOIN uploaded_flight_files_table ON uploaded_flight_files_table.Airline=received_flight_files_table.Airline)))
WHERE (received_flight_files_table.Processing_Month = [enter MMMYY];
There should sometimes be some blanks in the Uploaded_Date field as for example - in one table I might have received the files but not yet uploaded them.
Try to use LEFT JOIN instead of INNER JOIN.
https://www.diffen.com/difference/Inner_Join_vs_Outer_Join

Counting results from 2 tables base on a third table

I am trying to count number of questions and answers for every company but I want to count them in a single query.
So the problem is this: table pitanje (question) is linked with tvrtka (company)
pitanje.tvrtka_id=tvrtka.tvrtka_id and table answer (odgovor) is linked with question table odgovor.pitanje_id = pitanje.pitanje_id
I have tried with something similar to this and got some faulty results (I counted question and answers separately for testing).
SELECT tvrtka.naziv,
(SELECT COUNT(*) FROM pitanje WHERE tvrtka.tvrtka_id = pitanje.tvrtka_id) AS brojPitanja,
(SELECT COUNT(*) FROM odgovor WHERE odgovor.pitanje_id = pitanje.pitanje_id) AS brojOdgovora
FROM tvrtka
ORDER BY tvrtka.tvrtka_id
But all I get is some MySQL errors (unknown column, not uniqe alias etc.) now and can't get even to a faulty results.
If someone can just explain me the concept of the code above. A lot of answers are written like this but I can't figure out how to do it on my example.
With englisch names it would be something like this:
SELECT
c.name,
COUNT(DISTINCT q.question_id) as numQuestions,
COUNT(a.answer_id) as numAnswers
FROM company c
LEFT JOIN questions q ON q.company_id = c.company_id
LEFT JOIN answers a ON a.question_id = q.question_id
GROUP BY c.name
I let it to you, to translate the table and column names back to your schema.
What is wrong with my code?
Here:
(SELECT COUNT(*) FROM pitanje WHERE tvrtka.tvrtka_id = pitanje.tvrtka_id) AS brojPitanja,
(SELECT COUNT(*) FROM odgovor WHERE odgovor.pitanje_id = pitanje.pitanje_id) AS brojOdgovora
in your second subquery with WHERE odgovor.pitanje_id = pitanje.pitanje_id you are trying to reference a table (pitanje) from another subquery. This is not possible. You can only reference a table in the FROM clause of the outer query, which is tvrtka.

SQL - The fastest query for multiple INNERJOIN [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Which query is faster - (or it doesn't matter)?
SELECT *
FROM students as s
INNER JOIN hallprefs as hp
ON s.studentid = hp.studentid
INNER JOIN halls as h
ON hp.hallid = h.hallid
or
SELECT *
FROM students as s
INNER JOIN hallprefs as hp
INNER JOIN halls as h
ON hp.hallid = h.hallid
AND s.studentid = hp.studentid
Of course the original question is with way more tables.
The comments have all alluded to the same points, that it shouldn't matter in terms of performance, and that the second query is not ANSI compliant. The reason MySQL allows it is because
In MySQL, JOIN, CROSS JOIN, and INNER JOIN are syntactic equivalents (they can replace each other). In standard SQL, they are not equivalent. INNER JOIN is used with an ON clause, CROSS JOIN is used otherwise.
extracted from online documentation
So the ANSI equivalent of the second query is:
SELECT *
FROM students as s
CROSS JOIN hallprefs as hp
INNER JOIN halls as h
ON hp.hallid = h.hallid
AND s.studentid = hp.studentid;
Again, this rewrite should have no impact on performance, SQL is a declarative language, so you tell the engine what you want it to do, not how you want it to do it, so since the intention of the two queries is exactly the same, one would hope the optmiser arrives at the same plan for both. This is of course not always the case, although I am pretty certain it will be for all DBMS for simple cases like this.
When it comes to SQL, the answer to which is fastest/more efficient etc is almost always, it depends. It will depend on your schema, indexes, data types, data distribution, database vendor/version. So while general guidelines can be give, the real answer is to test.
As to which is better practice, I think it really depends on your intentions, The problem with the former is that you might decide you only want to left join on halls, so adapt your queries:
SELECT *
FROM students as s
CROSS JOIN hallprefs as hp
LEFT JOIN halls as h
ON hp.hallid = h.hallid
AND s.studentid = hp.studentid;
You introduce a Cartesian product, whereas the same change with the first query doesn't do this.
SELECT *
FROM students as s
INNER JOIN hallprefs as hp
ON s.studentid = hp.studentid
LEFT JOIN halls as h
ON hp.hallid = h.hallid;
Now, the intention could have been to have the Cartesian product, in which case the cross join solution is better for this situation. Once again, it depends, and your mileage may vary.

PHP Queries not working

This is working:
SELECT *
FROM ((((defect
JOIN project_testcase ON
defect.Test_Id=project_testcase.Test_Id)
JOIN testcase ON
defect.Test_Id=testcase.Test_Id)
JOIN project_pm ON
project_testcase.Project_Id=project_pm.Project_Id)
JOIN employee ON
employee.Emp_id=project_pm.Emp_id)
However, this does not work:
SELECT *
FROM ((((defect
JOIN project_testcase ON
defect.Test_Id=project_testcase.Test_Id)
JOIN testcase ON
defect.Test_Id=testcase.Test_Id)
JOIN project_pm ON
project_testcase.Project_Id=project_pm.Project_Id)
JOIN employee ON
employee.Emp_id=project_pm.Emp_id)
WHERE Project_Id LIKE '%$categ%'
As I have used JOIN tables and joined using Project_Id. Is that the error?
The first thing I would do to troubleshoot this is to paste it into an SQL formatter. This will help find syntax errors and could help you see a logic error. I would recommend freeformatter.com.
Second you can get rid of the parenthesis.
The Fix
You need to specify what table to get the Project_Id in the WHERE because it is in multiple tables, but for clarity I would always specify what table it comes from.
select
*
from
defect
join
project_testcase
on defect.Test_Id=project_testcase.Test_Id
join
testcase
on defect.Test_Id=testcase.Test_Id
join
project_pm
on project_testcase.Project_Id=project_pm.Project_Id
join
employee
on employee.Emp_id=project_pm.Emp_id
where
project_testcase.Project_Id like '%$categ%'
Project_Id in the where clause is ambiguous, you need to define it as you have done on your joins ie WHERE project_pm.Project_Id like '%$categ%'
In the where clause of the 2nd query you need to tell the rdbms exactly which Project_Id field you want to filter on, since multiple tables contain the Project_Id field, e.g. project_pm.Project_Id.
Starting by removing all those unnecessary parenthesis, formatting and aliases reveals a fairly simple query underneath.
select * --This should really be the columns you actually need instead of all of them
from defect d
join project_testcase ptc on d.Test_Id = ptc.Test_Id
join testcase t on d.Test_Id = t.Test_Id
join project_pm p on ptc.Project_Id = p.Project_Id
join employee e on e.Emp_id = p.Emp_id
where p.Project_Id like '%$categ%'
Of course this begs the question of why do you have text like that in a column named Project_Id? That does not look like a project id to me. And since you are using a leading wildcard you have a nonSARGable query so you have eliminated the ability of index seeks on that column.

Stuck on a DQL left join query

I have two tables:
Users <----> Questions
They use a ManyToMany relation table to keep track of which user answered which question.
Users <----> UsersQuestions <----> Questions
Now I need to write a query which fetches all the questions a specific user id has NOT answered yet.
The following native query works fine:
SELECT * FROM questions q
WHERE q.id NOT IN (
SELECT question_id FROM users_questions
WHERE user_id = 4
);
But I directly access the UsersQuestions table in this query and I haven't found a way to do so in Doctrine yet, I don't even think it's possible.
The only way to access that table is by joining on a property of my Question class, thus I tried to rewrite the query to the following one which also works fine as a native query:
SELECT * questions q
LEFT JOIN users_questions uq
ON q.id = uq.question_id AND uq.user_id = 4
WHERE uq.user_id IS NULL;
I was assuming that I could simply rewrite this into DQL as the following query:
SELECT q FROM MyBundle:Question q
LEFT JOIN q.usersAnswered uq WITH uq.id = 4
WHERE uq.id IS NULL
When I call $query->getSql() I get the following output:
SELECT * FROM mybundle_questions g0_
LEFT JOIN users_questions u2_
ON g0_.id = u2_.question_id
LEFT JOIN mybundle_users g1_
ON g1_.id = u2_.user_id AND (g1_.id = 4)
WHERE g1_.id IS NULL
Which to me looks fine given my very basic knowledge on Doctrine and queries in general. However, this fetches and returns ALL the questions which are in the table and not only the ones which this users hasn't answered yet.
Did I make a mistake somewhere? Or is there any other/easier way to fetch these unanswered questions? I feel like I'm reinventing the wheel here.
Been stuck on this for days and every attempt that I make in native SQL works fine, but I can't translate it to DQL. Any help would be appreciated.
I've solved my problem with the following query. Looks like it WAS possible to create a subquery after all.
SELECT q FROM MyBundle:Question q
WHERE q.id NOT IN (
SELECT uq.id FROM MyBundle:User u
INNER JOIN u.questionsAnswered uq
WHERE u.id = 4
)
Which Doctrine translates to the following query:
SELECT * FROM myBundle_questions g0_
WHERE g0_.id NOT IN (
SELECT g1_.id FROM myBundle_users g2_
INNER JOIN users_questions u3_
ON g2_.id = u3_.user_id
INNER JOIN myBundle_questions g1_
ON g1_.id = u3_.question_id
WHERE g2_.id = ?
)
For some reason the previous query, although it looked good in my eyes, didn't work. Must have something to do with how Doctrine handles the left join / null situations. However, this query in which I approach the problem from a different angle work perfectly.