Stuck on a DQL left join query - mysql

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.

Related

learning mysql, JOIN query

i'm a beginner on MYSQL db and i'm trying to play around with the query and relations.
i have created 2 tables, one is 'users' which contain the field staff_ID and the other is 'reports' which also contain the table field staff_ID of the user submitting the reports.
on the relations (see picture) i have connect the 2 staff id field.
every user can submit more than one reports, so i'm try to query and get only the reports of one users(staff_ID).
I understood i have to use the JOIN keyword in order to obtain the data..
i tried the following query but it gave me all the result for all the users.
SELECT u.staff_ID
, u.Name
, r.id_report_show
, r.date_report
FROM users u
JOIN reports r
ON r.staff_ID = u.staff_ID
but I would like to have the report only of one specific user like staff_ID = 04033
probably i understood wrong how this query JOIN work, i'm looking for some help.
Thanks
You are almost there. Your join is perfect. You just need a where clause.
SELECT users.staff_ID, users.Name, reports.id_report_show, reports.date_report
FROM `users` INNER JOIN reports ON reports.staff_ID = users.staff_ID
where users.staff_ID = 04033
Or you can also mention it within on clauses:
SELECT users.staff_ID, users.Name, reports.id_report_show, reports.date_report
FROM `users` INNER JOIN reports
ON reports.staff_ID = users.staff_ID and users.staff_ID = 04033
Since it's inner join both the query will produce same output. But for left join those might produce different result. It's a good practice to use where clause instead of mentioning the condition in on clause.

SQL problem with JOIN statement (multiple results from 1 table)

So I have a SQL query that selects quiz_questions and quiz_question_options
But when I run my SQL query I only get 1 result from quiz_option (in my database I have 3 options for each question). How would I be able to display all 3 options for every question?
Tables:
quiz_question
-id (PK)
-quiz_id(FK)
-question
quiz_question_option
`-id (PK)
-quiz_question_id(FK)
-quiz_option`
This is my code so far:
SELECT quiz_question.question,quiz_question_option.quiz_option
FROM quiz_question_option
LEFT JOIN quiz_question
ON quiz_question.id = quiz_question_option.quiz_question_id
ORDER BY RAND() LIMIT 5
The limit will change depending on user input
EDIT:
The result i get is:
question |quiz_option
1.question|1.answer
2.question|2.answer
What I need to get is:
question |quiz_option
1.question|1.answer
1.question|2.asnwer
1.question|3.answer
2.question|1.answer
2.question|2.answer
3.question|3.answer
etc...
2.EDIT:
I need to make a sql query for my project (website)
so the user will select how many questions he wants to have.
On the next page it would display the questions. I already have the code to display random questions. But I don't know how to display the options for the selected question.
seems you want to ignore the relationship. what you want to achieve is something like cross join
select t1.question, t2.quiz_option
from quiz_question_option t1
cross join quiz_question t2
I believe INNER join would help you.
Try this:
SELECT quiz_question.question, quiz_question_option.quiz_option
FROM quiz_question_option AS O
INNER JOIN quiz_question AS Q
ON Q.id= O.quiz_question_id

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 - Query Assistance [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 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%'

SQL query to join columns in result

I'm a complete SQL noob and have no idea how to utilize JOINs. If someone could help with this query, it would be great.
I have a table questions which contains two columns: queid and que.
Another table options, contains the corresponding options for the questions, and has columns optionid, queid,option.
How can I do a SELECT statement such that I can join both tables together based on queid ?
Something like:
SELECT * from questions,options where queid=1
You should try this:
SELECT que.*, opt.* FROM questions que
INNER JOIN options opt ON que.queid = opt.queid
WHERE que.queid = 1
INNER JOIN loads questions and options having at least one corresponing record in every table.
If you need to get all questions (even the ones not having options) you could use
SELECT que.*, opt.* FROM questions que
LEFT JOIN options opt ON que.queid = opt.queid
WHERE que.queid = 1
LEFT JOIN always loads questions and, if they have options, their options too; if not you get NULL for options columns.
May be by
SELECT * FROM questions q JOIN options o ON q.queid=o.queid WHERE q.queid=1
SELECT q.*,o.* FROM questions q
JOIN options o ON q.queid = o.queid
WHERE q.queid = 1
SELECT *
FROM questions
JOIN options ON questions.queid = options.queid
WHERE questions.queid = 1
You can join two related tables using the column that they have in common.
in your case you can write :
SELECT * FROM Questions as Q INNER JOIN Options O ON Q.queid=O.queid WHERE Q.quid=1
You can also omit the where part like this :
SELECT * FROM Questions as Q INNER JOIN Options O ON Q.queid=O.queid AND Q.quid=1
There are different kind of joins :
INNER
OUTER(Left,Right,Full)
By inner join you mean that only records that are common in both tables are returned
When you use outer join all the records on the given side are return plus the records that have corresponding values on the other side otherwise instead of the other side values you will get null.