I have page called questions where the user gets asked questions and he/she has the option to answer them. The questions are pulled from a table called questions. When a question gets answered, a table in my database called answered_questions registers the id of the question answered and the id of the user who answered the question. The purpose of this is to hide the answered questions when the user accesses the page again.
On page load I'm trying to join the two tables and see if the question_id exists in both tables where the userID is that of the logged in user. If the id does exist in both tables then it shouldnt display the result per the use of <>. Problem is that its looping several times for each iteration when I try the following query:
SELECT questions.question_id, questions.user_id
FROM `questions`
JOIN `answered_questions`
ON questions.question_id <> answered_questions.question_id
WHERE answered_questions.user_id = ".$userID."
But it works fine when I use this
SELECT questions.question_id, questions.user_id
FROM `questions`
JOIN `answered_questions`
ON questions.question_id **=** answered_questions.question_id
WHERE answered_questions.user_id = ".$userID."
I sense that I'm doing something wrong with the logic of it all. Any help or clues would be highly appreciated.
To get unanswered questions You can use LEFT JOIN:
SELECT questions.question_id, questions.user_id
FROM questions
LEFT JOIN answered_questions
ON answered_questions.question_id = questions.question_id
AND answered_questions.user_id = ".$userID."
WHERE answered_questions.question_id IS NULL
Related
I want to build a system in which users can submit quiz questions and users can also rate those questions.
There are two tables relevant to my problem:
"Question", which contains a questionID, a userID(from the user who
submitted the question), a correct answer, a wrong answer, another
wrong answer and a boolean that is set to true when the question
survived the validation process.
"Validation", which contains a questionID for which question is validated, a UserID for which user validated it and a validation (0,
1 or 2 depending on the rating the user gave the question).
To give users questions that need rating, I need a MySQL query with which I receive a question that is:
not through validation yet (validated bool = false)
not made by the user requesting it
not already validated by the user requesting it
the first question in the list of results with these factors
EDIT: I found a solution, look at the bottom edit.
I have tried the following query:
set #UserId=5;
SELECT q.id, q.question, q.correct_answer, q.wrong_answer1, q.wrong_answer2
FROM question q
LEFT JOIN validation v ON v.question_id=q.id
WHERE q.validated = 0
AND q.user_id!=#UserId
AND v.user_id!=#UserID
ORDER BY q.id
LIMIT 1
I exclude questions already through validation with WHERE q.validated = 0.
I make sure it's the first question in the list of results with ORDER BY q.id LIMIT 1
I exclude questions made by the user requesting it with q.user_id!=#UserId
This query returns nothing, though.
The question table contains some unvalidated questions. The validation table is empty.
I know the mistake lies somewhere within the LEFT JOIN validation v ON v.question_id=q.id and v.user_id!=#UserID parts, but I don't know how to translate my will to MySQL..
EDIT: I found a solution that worked for my problem:
set #UserId=5;
SELECT q.id, q.question, q.correct_answer, q.wrong_answer1, q.wrong_answer2 FROM question q
WHERE NOT EXISTS
(SELECT * FROM validation v WHERE v.user_id=#UserID AND q.id = v.question_id)
AND q.validated = 0 AND q.user_id!=#UserId
But, I read this method is very bad for performance.
Is there a more performant method?
You have to check for null in v.user_id because there is no entry.
This query works:
set #UserId=5;
SELECT q.id, q.question, q.correct_answer, q.wrong_answer1, q.wrong_answer2
FROM question q
LEFT JOIN validation v ON v.question_id=q.id
WHERE q.validated = 0
AND q.user_id!=#UserId
AND v.user_id is null or v.user_id!=#UserId
ORDER BY q.id
LIMIT 1
MySQL.
I have two tables, one is "Questions" and the other is "Answers"
The Questions table:
- question_id
- user_id
- question
The Answers table:
- answer_id
- question_id
- user_id
- answer
- correct
The goal is to get all questions (and associative answers) based on a user's id. I've been able to get all of the answers, however I'm only getting one question. I can see why it's only getting a single question, but I don't have any idea how to go about getting the question text for each answer.
Here's the code that I'm using right now. Where id_in is an input value on a saved procedure. The issue is that it gives me all of the answers for each question, but all of them return the same question text. I feel like possibly a type of join would be better here, but we haven't started learning about them yet and I hardly know anything about them as is.
BEGIN
DECLARE question_text VARCHAR(40);
SELECT question INTO question_text FROM questions WHERE user_id = id_in;
SELECT question_text, Q.* FROM answers AS Q WHERE user_id = id_in;
END
Yes, this is homework. I'm just completely lost as to what I need to be doing.
Left joins allow for All things in the left table, and only the matching things in the right table. In my example I may have A and Q mixed up but I think this is the general gist of it. You can also take the user_id = in_id and move that to a wear, but filter on the join should be faster.
SELECT
Q.QUESTION
, A.ANSWER
, A.CORRECT
FROM ANSWERS A
LEFT JOIN QUESTION Q
ON A.QUESTION_ID = Q.QUESTION_ID
AND A.USER_ID = Q.USER_ID
AND A.USER_ID = ID_IN
AND Q.USER_ID = ID_IN
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.
I have a MYSQL 'activity' table where all activity by a user gets logged. Let's say that a user's activities can be either to ask a question or answer a question. So if a user asks a question, their question gets put into the 'question' table and also the activity gets put into the 'activity' table. Same thing if user provides an answer, except that the answer goes into the 'answers' table and the 'activity' table.
The question table's fields are:
q_id question
The answers table's fields are:
a_id q_id answer
The activity table's fields are:
activity_id q_id user_id action_type
(There are more columns then shown above, but these illustrate the point.)
What I want to be able to do is show a user's recent actions on the site, and actually show what the actions were.
My current MYSQL query simply joins the activity table with the question table as follows (using PDO):
"SELECT *
FROM activity
LEFT JOIN question ON activity.q_id = question.q_id
WHERE activity.user_id = :user_id
ORDER BY activity.a_id desc"
This works okay, and can always give me the question for display in the activities list. However, if the activity that is returned is an answer, I would like to be able to show the answer as well. I tried just using a triple join as follows:
"SELECT *
FROM activity
LEFT JOIN question ON activity.q_id = question.q_id
LEFT JOIN answers ON activity.q_id = answers.q_id
WHERE activity.user_id = :user_id
ORDER BY activity.a_id desc"
But this just gives me a list of rows that is twice as long as the first query, and does not display the answers when the action_type was an answer.
I figure this should be possible, but the more I think about it I believe that maybe I should scrap the activity table and just perform the query directly on the question and answers tables with a UNION? Any opinions on this decision, and any thoughts on the queries?
You could use an outer join, which would return everything in the activity table, even if there isn't a corresponding row in the answer table:
SELECT *
FROM activity
LEFT JOIN question ON activity.q_id = question.q_id
LEFT OUTER JOIN answers ON activity.q_id = answers.q_id
WHERE activity.user_id = :user_id
ORDER BY activity.a_id desc
I'm assuming that for every q_id value in the activity table, there's always going to be one corresponding row in the question table.
To fix the problem with the duplicate answers, I'd add an a_id field to the activity table. For the question activity, you'd set it to NULL, and for each answer you'd set the a_id field to the appropriate a_id value to identify which answer goes with the activity. You'd then adjust the SQL above as follows:
SELECT *
FROM activity
LEFT JOIN question ON
activity.q_id = question.q_id
LEFT OUTER JOIN answers ON
activity.q_id = answers.q_id AND
activity.a_id = answers.a_id
WHERE activity.user_id = :user_id
ORDER BY activity.a_id desc
I am trying to create a join statement to solve my problem but cannot get my head around it.
I am a new to join statements so please bear with me if my sql statement is nonsense.
I have two tables, one is a table of questions where users have asked questions about items for sale.
Second is a table of items that the user has asked a question about.
Table one called questions consists of question_ref, questioner_user_ref, item_ref, seller_ref, question_text, timestamp
questions
===========
+--------------+--------------------+---------+-----------+--------------+----------+
| question_ref |questioner_user_ref |item_ref |seller_ref |question_text |timestamp |
+--------------+--------------------+---------+-----------+--------------+----------+
Table two called my_item_comments consists of questioner_ref, item_ref, last_question_ref
my_item_comments
===========
+---------------+---------+------------------+
|questioner_ref |item_ref |last_question_ref |
+---------------+---------+------------------+
I have set up table two to keep track of items that the user has asked questions about so they can be informed when someone else asks the seller a question or the seller answers.
So I want to create a recordset of questions that
a). Someone has answered a question about an item the user is selling
b). A seller has replied to a question the user asked,
c). A third user has asked a question about an item that the user has also asked a question about.
A bit like facebook's commenting system, where you are informed about comments people have made on statuses that you have commented on.
So my current sql statement is as follows
$user_ref= current logged in user
$sql=mysql_query("
SELECT * FROM questions
LEFT JOIN my_item_comments
ON questions.item_ref=my_item_comments.item_ref
WHERE questions.questioner_user_ref!='$user_ref'
AND (questions.seller_ref='$user_ref' OR questions.item_ref=my_item_comments.item_ref
ORDER BY timestamp DESC");
The results don't work and I think its because of the OR questions.item_ref=my_item_comments.item_ref but for the life of me I cannot work it out.
Any help would be greatly appreciated, even if it means restructuring my database with more tables or new fields in the tables.
thanks in advance, Barry
SELECT * FROM questions
LEFT JOIN my_item_comments ON questions.item_ref=my_item_comments.item_ref
WHERE
questions.questioner_user_ref != '$user_ref' AND
(questions.seller_ref='$user_ref' OR questions.item_ref=my_item_comments.item_ref)
ORDER BY timestamp DESC
I think you were missing a ) to enclose the OR clause (in the example above I added it)
You should try to improve readability for yourself and us so that it is easier to debug and easier for us to help you :-)
$q = "
SELECT *
FROM questions
RIGHT JOIN my_item_comments ON questions.item_ref = my_item_comments.item_ref
WHERE questions.questioner_user_ref != '".$user_ref."'
AND ( questions.seller_ref = '".$user_ref."'
OR questions.item_ref=my_item_comments.item_ref
)
ORDER BY timestamp DESC";
$rs = mysql_query($q);
And preferably just the query with dummy data
SELECT *
FROM questions
RIGHT JOIN my_item_comments ON questions.item_ref = my_item_comments.item_ref
WHERE questions.questioner_user_ref != 'dummy_ref'
AND ( questions.seller_ref = 'dummy_ref'
OR questions.item_ref=my_item_comments.item_ref
)
ORDER BY timestamp DESC
Try a right join for your query. Left join will indeed get all the rows.