2009-07-29 8 views
2

J'essaie de créer une fonction de sondage simple en utilisant php et sql. J'ai trois tables:Complexe (ish) requête de jointure et de comptage SQL

Questions

qui contient simplement chaque question posée

question_id | question_text | created_at

Réponses

qui contient chaque réponse pour chaque question

question_id | answer_id | answer_text

Questions répondues

qui enregistre qui a voté pour chaque option

question_id | answer_id | user_ip

J'essaye d'écrire une question qui retournera une question simple (la plus récente) avec toutes les réponses possibles à cette question et finalement un compte de chaque réponse à chaque question. Je sais que je devrai utiliser une clause GROUP BY et une possible LEFT OUTER JOIN, mais la syntaxe exacte est celle qui m'échappe.

Un conseil serait grandement apprécié. Merci.

+0

Pourquoi conserver 'question_id' dans la troisième table? 'question_id' est défini par' answer_id'. – Quassnoi

+0

@Quassnoi: Sauf si sa clé primaire est composite (question_id, answer_id). –

+0

@Hosam Aly: vous pensez qu'une réponse peut être appliquée à plusieurs questions? – Quassnoi

Répondre

1

Cette requête devrait fonctionner sur la plupart des DBMS:

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 
+0

Votre requête ne tient pas compte des cas où deux questions ont été créées en même temps - Vous devez remplacer la sous-requête par WHERE q.question_id = (SELECT TOP 1 question_id FROM QUESTIONS ORDER BY created_at DESC) – Justin

+0

Avoir deux questions avec le même 'created_at' Le temps serait un problème pour le PO, car il devrait avoir un critère précis pour identifier la question la plus récente qu'il a demandée. Utiliser 'TOP' ne résoudrait pas le problème, car 1) il retournerait un enregistrement arbitraire, et 2) il n'est pas supporté par toutes les bases de données (par exemple, MySQL et PostgreSQL utilisent' LIMIT' à la place). –

+0

Merci, cela semble être le plus proche jusqu'à présent de ce dont j'ai besoin. Cependant, il renvoie deux lignes pour chaque réponse. par exemple: Quelle est votre couleur préférée? bleu orange, rouge bleu orange, rouge – Dan

1

En supposant que vous 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 
0
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 

devrait fonctionner (même si je ne l'ai pas testé).

+0

Un formatage rendrait cette réponse beaucoup plus lisible! –

+0

Formaté maintenant :) –

+0

C'est beaucoup mieux. Mais cette question sélectionne la question la moins récente (par opposition à la plus récente, comme l'exige le PO). –

2

Ceci est très similaire à la logique dans cet article http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/.

Essentiellement, vous avez besoin d'un sous-requête qui sélectionne le seul enregistrement/question qui vous intéresse, ainsi qu'une requête externe pour sélectionner les informations relatives à ce dossier que vous êtes intéressé par

(je pourrais poster une autre SQL déclaration à ajouter à la belle collection qui a déjà été posté, mais je pensais que j'essaierais de faire la lumière sur la façon dont les autres requêtes postées fonctionnent)