tags:

views:

794

answers:

4

Hi, I'm trying to create a simple poll function using php and sql. I have three tables:

Questions

Which simply contains each question asked

question_id | question_text | created_at

Answers

Which contains each answer for each question

question_id | answer_id | answer_text

Answered Questions

Which records who has voted for each option

question_id | answer_id | user_ip

I'm trying to write a query which will return a single question (the most recent) along with all the possible answers to that question and finally a count of each answer to each question. I know I will have to use a GROUP BY clause and possible LEFT OUTER JOIN, but the exact syntax is eluding me atm.

Any advice would be greatly appreciated. Thanks.

+1  A: 

Assuming you're usnig MySQL:

SELECT  q.* ,
        (
        SELECT  COUNT(*)
        FROM    answered_questions aq
        WHERE   aq.answer_id = a.answer_id
                AND aq.question_id = q.question_id
        ) AS votes
FROM    (
        SELECT  *
        FROM    question
        ORDER BY
                created_at DESC
        LIMIT 1
        ) q
LEFT OUTER JOIN
        answers a
ON      a.question_id = q.question_id
Quassnoi
A: 
SELECT
    questions.question_id,
    questions.question_text,
    answers.answer_id,
    answers.answer_text,
    COUNT(answered_questions.user_ip)
FROM
    questions,answers,
    answered_questions
WHERE
    questions.question_id=answers.question_id
    AND
    questions.question_id=
        (SELECT
            question_id
            FROM questions
            ORDER BY questions.created_at
            LIMIT 1
        )
    AND
    answered_questions.question_id=questions.question_id
GROUP BY
    questions.question_id

should work (although I haven't tested it).

Richy C.
Some formatting would make this answer much more readable!
Hosam Aly
Formatted now :)
Richy C.
That's much better. But this query would select the least recent question (as opposed to the most recent one as required by the OP).
Hosam Aly
A: 

This query should work on most DBMSs:

select q.question_id, question_text, a.answer_id, a.answer_text, count(user_ip)
  from questions q
 inner join answers a on (q.question_id = a.question_id)
  left join answered_questions aq on (a.question_id = aq.question_id
                                      and a.answer_id = aq.answer_id)
 where created_at = (select max(created_at)
                       from questions
                     )
 group by q.question_id, a.answer_id, q.question_text, a.answer_text
Hosam Aly
Your query doesnt account for cases where two questions were created at the same time - You should replace the subquery with WHERE q.question_id = (SELECT TOP 1 question_id FROM QUESTIONS ORDER BY created_at DESC)
Kragen
Having two questions with the same `created_at` time would be a problem for the OP, as he should have a definite criteria for identifying *the most recent question* he asked for. Using `TOP` would not solve the problem, as 1) it would return an arbitrary record, and 2) it is not supported by all databases (e.g. MySQL and PostgreSQL use `LIMIT` instead).
Hosam Aly
Thanks, this seems to be the closest so far to what I need. However, it is returning two rows for each answer. eg:What is your favourite colour?blueorangeredblueorangered
Dan
@Dan: This should never happen, unless you have something incorrect in your data. We are grouping by both `question_id` and `answer_id`, so a single row in the table `answers` cannot appear twice. Is it possible that there is some duplication in your data?
Hosam Aly
+1  A: 

This is very similar to the logic in this article http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/.

Essentially you need a subquery which selects the single record / question you are interested in, as well as an outer query to select the information related to that record that you are interested in

(I could post another SQL statement to add to the nice collection that have already been posted, but I thought I'd try and shed some light onto how the other posted queries work)

Kragen