MySQLFiddle here: http://sqlfiddle.com/#!2/15d447/1
I have a single table I am trying to work with:
Table 1: user_answers table (stores users answers to various questions)
The notable values that are stored are the users id (column uid), the question id for the question they are answering (column quid), the answer to the question (column answer) and the importance of their answer (column importance).
The end result I want:
I'd like to be able to grab all the questions that any two users have answered, excluding any answers from questions that have either not been answered by the other party, or answers to the same question which have a value of 1 for either user in importance. Again, this will only ever be used to compare two users at a time.
I've been pretty unsuccesful in my attempts, but here is what I've tried, just piecing things together:
#attempt one: trying to exclude answers that were not answered by both users
SELECT * FROM user_answers AS uid1
JOIN user_answers AS uid2 ON uid1.uid = uid2.uid
WHERE uid1.uid = 1
AND uid2.uid = 20008
AND uid1.quid IS NOT NULL
AND uid2.quid IS NOT NULL;
This returns no results but I'm not exactly sure why.
#attempt two: trying to exclude where answers are the same for both users
SELECT * FROM user_answers AS uid1
LEFT JOIN user_answers AS uid2 ON (uid1.uid = uid2.uid AND uid1.answer <> uid2.answer)
This gives me results, but seems to be doubling up on everything because of the join. I also tried in this attempt to eliminate any answers what were the same, which seems to be working in that sense.
Any guidance is appreciated.
Thanks.
You can answer your question using an aggregation query. The idea is to using the having clause to filter the rows for the conditions you are looking at.
Because you are not interested at all in questions with importance = 1 those are filtered using a where clause:
select ua.quid
from user_answers ua
where importance <> 1 and uid in (1, 20008)
group by ua.quid
having sum(uid = 1) > 0 and
sum(uid = 20008) > 0;
If you want to include the answers, you can do:
select ua.quid,
group_concat(concat(uid, ':', answer) order by uid) as answers
Just a simple version of what you need.
select *
from user_answers a,
user_answers b
where a.quid = b.quid
and a.uid <> b.uid
and 1 not in (a.importance, b.importance)
If you like to filter just the questions just change the * for distinct a.quid
See it here on fiddle: http://sqlfiddle.com/#!2/15d447/15
Related
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.
I have 3 tables (user, questions, answers) in the question table i have id_question and question, in the answer table I have id_question, user_id and answer. I want to run a query that gives me the number of answer's per question.
I want a column that has all questions that were answered (not the id_question) and 3 other columns (yes, no, maybe) that have the number of times that that answer was given to a question. The question column can't have repeated questions (even though users can answer the same questions and give different answers, I want the number of yes, nos and maybes to each question). I'm only created the yes column, having trouble in creating the other 2
Here's what I did so far:
SELECT
questions.question, COUNT(answers.answer) As Yes
FROM
answers
INNER JOIN
questions ON questions.id_question = answers.id_question
WHERE
answer = 'yes'
GROUP BY
question
ORDER BY
questions.id_question ASC
SELECT questions.question,
SUM(IF(answer='yes', 1, 0)) AS Yes,
SUM(IF(answer='no', 1, 0)) AS No,
SUM(IF(answer='maybe', 1, 0)) AS Maybe
FROM answers
INNER JOIN questions ON questions.id_question=answers.id_question
GROUP BY question
ORDER BY questions.id_question ASC
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 questions table like below
and answers table like below
every question has multiple answers
How can I make query to return the result as below table
You have to order by two columns - q_id and ans_id. Since in question_tb there is no ans_id field you can put 0 instead.
select t.id, t.q_content from
(
select q_id, q_content, 0 k, q_id id from question_tb
union
select ans_q_id, ans_content, ans_id, ans_id from answer_tb
) t order by t.q_id, t.k
Hmmm.. I think you need to re-think your structure a bit: the last table (or query result) needs a column to designate which is the question, and which are the answers, and also to indicate the correct answer.
Also, I assume that each set of questions (and answers) will be tied to a particular user, so you will need a user_key in the answer table, as well.
SELECT Q.q_content AS question,
ANS.ans_content AS answer,
ANS.is_correct,
ANS.user_id,
FROM Question_TB Q
INNER JOIN tb_answer ANS
ON ANS.ans_q_id = Q.q_id
ORDER BY ANS.user_id, Q.q_id
I'm writing an application where people ask questions, and get answers in the form of a survey. Each question has 2 options, plus a default option(s). When a person answers the question, they can choose from either the 2 options set by the asker, or the default option(s) chosen by me. For instance, if the question is Vanilla vs. Chocolate, options will be Vanilla, Chocolate, and Neither. I want to be able to tabulate the percentage of options chosen for a question, i.e., 25% say chocolate, 30% say vanilla, 45% say neither.
I'll start by showing the table structure and the query I'm running.
These are the tables involved (Note: these are not the full table structures):
--questions--
id
user_id
topic
description
--options--
id
text
default (bool)
--questions_options--
question_id
option_id
--answers--
id
question_id
user_id
option_id
Here is the query:
SELECT
options.id AS option_id, options.text, options.default,
ROUND(
IFNULL(
(COUNT(answers.option_id) * 100)
/
(SELECT COUNT(answers.option_id) FROM answers WHERE question_id = QUESTION_ID)
, 0)
, 2) AS percentage
FROM options
LEFT JOIN questions_options ON questions_options.option_id = options.id
LEFT JOIN answers ON answers.option_id = options.id
WHERE questions_options.question_id = QUESTION_ID
OR options.default = '1'
GROUP BY options.id
ORDER BY percentage DESC, option_id ASC
Where QUESTION_ID is an integer constant.
The problem is the query is not limiting answers to only those given for a particular question, and because the options are many to many with questions, I'm getting results like 600% for vanilla (if multiple questions use vanilla as an option). In cases where the options are unique to ONE question, then the percentages make sense, except for the default options, which are present for all questions. I tried putting WHERE answers.question_id = QUESTION_ID in there, but it did not work.
Any solutions?
Thanks
You're doing the joins in the wrong direction - you're looking at options first, even though you have specifically stated you want things tabulated by question. This means that you're getting results for all options, regardless of whether or not they even relate to your question...
Oh, and I'm assuming that answer_id is mapped to question_id, or you're not going to be able to get any meaningful results (that is - answers are not otherwise mapped to questions...)
Try this query instead:
SELECT b.id, b.text, b.default, (SELECT IFNULL(
ROUND((COUNT(c.id) * 100) /
(SELECT COUNT(d.id)
FROM answers as d
WHERE d.answer_id = a.question_id)
, 2)
, 0)
FROM answers as c
WHERE c.answer_id = a.question_id
AND c.option_id = a.option_id) as percentage
FROM questions_options as a
JOIN options as b
ON b.id = a.option_id
WHERE a.question_id = QUESTION_ID
ORDER BY percentage DESC, a.option_id ASC
Please note that I don't have a copy of MySQL to run this against, and I would normally implement with CTEs (which I have been informed are not supported for MySQL).
EDIT:
In light of the fact that 'default' options may not be mapped through the questions_options table, try this:
SELECT a.id, a.text, a.default, IFNULL(
ROUND((b.answerCount * 100) /
(SELECT COUNT(c.id)
FROM answers as c
WHERE c.answer_id = QUESTION_ID)
, 2)
, 0)
FROM options as a
LEFT JOIN (SELECT c.option_id, count(c.id) as answerCount
FROM answers as c
WHERE c.question_id = QUESTION_ID
GROUP BY c.option_id) as b
ON b.option_id = a.id
Please note that you will still get "meaningless" '0' results for every 'default' answer that was not presented to survey respondents - and no way to distinguish these from any actual '0' results results for 'default' answers that were presented to respondents. You are likely to be far better off placing the so called 'default' options in the questions_options table - as it is, you have no way to determine all the options that were presented to respondents (just which ones you have answers to, which is quite different); this may be a huge business-accountability issue for your company. In addition, some 'default' options may not make sense in context - "Do you prefer your tea hot or cold", "Yes".
Issues that I can see:
You GROUP BY options.id which means you are getting random values for options.text and options.default. This may or may not change your results depending on the structure of your data. If there are multiple rows per id then it will be inaccurate or misleading data.
You have a WHERE clause for your divisor but not your dividend in the percentage calculation - this means you will never have a lower count for the dividend. Try putting a WHERE question_id = QUESTION_ID to the first COUNT statement.