2010-10-14 14 views
1

Tout d'abord, c'est une tâche à faire, donc je cherche de l'aide, pas des solutions. Laissez-moi essayer d'expliquer mon schéma. J'ai trois tables que nous appellerons les utilisateurs (avec l'identifiant et le nom des colonnes), les parties (avec les colonnes id, partydate et user_id) et les questions (avec les colonnes id, createdate et user_id). Mon exigence est de montrer à chaque utilisateur le nombre de fêtes au cours de la dernière année et les questions créées au cours de la dernière année. Au début, j'avais quelque chose comme ça:Multiples jointures SQL avec nombre, ayant des problèmes

SELECT users.id, users.name, 
COUNT(parties.id) AS numparties, COUNT(qustions.id) AS numquestions 
FROM users 
FULL JOIN parties ON users.id=parties.user_id 
FULL JOIN questions ON users.id=questions.user_id 
WHERE (parties.partydate > NOW() - interval '1 year' OR parties.partydate IS NULL) 
OR (questions.createdate > NOW() - interval '1 year' OR questions.createdate IS NULL) 
GROUP BY users.id, users.name 

Maintenant ça marche, presque! Le problème est que, si un utilisateur n'a pas de parties ou de questions au cours de l'année écoulée, elles n'apparaissent pas du tout dans le résultat. Je veux qu'un tel utilisateur apparaisse, je veux juste qu'il les montre avec 0 pour chaque numpartties et numquestions. Ce dont je pense avoir besoin ici, c'est d'une sorte de comptage conditionnel, où je veux seulement COUNT (parties.id) O WH la partydate de ce parti est dans l'année écoulée, et la même chose pour les questions. Je ne suis pas sûr de savoir comment faire ça. J'ai une manière hacky-contournée de faire ce que je veux, où je UNION la requête ci-dessus avec une copie presque identique de lui-même, sauf que j'utilise SUM (0) pour numparties et numquestions et ma déclaration WHERE est juste là où la date est < = au lieu de>. Je pense que ce n'est pas la meilleure façon de s'y prendre.

Des pointeurs dans la bonne direction? Merci pour l'aide!

+0

Ajustement stylistique: S'il y a une possibilité NULL, je la mets toujours en premier, comme dans '(parties.partydate IS NULL OR parties.partydate> NOW() - intervalle '1 an ') –

Répondre

1

Jetez un oeil à ceci: http://www.w3schools.com/sql/sql_join_left.asp. Je pense que cela pourrait vous orienter dans la bonne direction.

+0

D'accord. Si vous avez des enregistrements d'utilisateur qui n'ont pas de correspondants et/ou de questions, mais que vous voulez montrer l'utilisateur, alors une jointure externe est le moyen de le faire. Sinon, vous limiterez votre jeu d'enregistrements à ceux qui ont des correspondances dans les trois tables. – Henry

0

pense que je l'ai avec ceci:

SUM(CASE WHEN (parties.partydate > NOW() - interval '1 year') THEN 1 ELSE 0 END) as numparties 

et juste enlevé les clauses WHERE.

0

Je pense que j'aurais recours à une sous-requête pour cela. Les questions de devoirs sont amusantes à répondre, je peux fortement coder ce code. Prenez l'ensemble de la requête que vous avez et appelez-le «x».

La première chose que vous voudrez est une liste de tous les utilisateurs, indépendamment du nombre de questions qu'ils ont posées.

Select distinct users.id,users.name from users 

qui vous donnera une liste complète de vos utilisateurs. La requête que vous avez ci-dessus vous donne des appels ... donc gauche rejoint les deux ensemble.

Select (fields you want) 
from users 
left join (enter you query above here) x on x.id = users.id 

Espérons que la logique ici a du sens pour vous. Utilisez une requête pour obtenir la liste des utilisateurs et la joindre à la sous-requête pour obtenir leur nombre.

modifier pour ajouter: cela ramènera des valeurs nulles chaque fois qu'il n'y a pas d'enregistrements. Vous pouvez faire en sorte que votre instruction select affiche des valeurs nulles à 0