2009-09-16 9 views
0

J'ai trois tables, qui sont chacune 1: n. Une entrée dans table1 a n entrées dans table2, et ainsi de suite. Appelons les voitures, les roues et les vis pour l'illustration. Les vis peuvent être propres (1) ou rouillées (2). Je me joins à eux, parce que je veux compter deux choses. D'abord, je veux avoir des rangées me disant combien de bonnes/mauvaises vis par roue j'ai pour chaque voiture. Donc, fondamentalement, je reçois:Rejoindre des sous-requêtes, compter et grouper

car_id wheel_id screw_state count(screws) 
    1   1   1   3 
    1   1   2   7 
    1   2   1   5 
    1   2   2   3 
    2   1   1   1 
       ... and so on... 

Maintenant, je veux un deuxième fait, à savoir combien de vis rouillées propres et j'ai pour toutes les roues par voiture, sans avoir besoin de connaître chaque numéro spécifique par roue. Donc, fondamentalement, maintenant je laisse juste à côté du GROUP BY sur wheel_id, comme ceci:

car_id screw_state count(screws) 
    1   1    8 
    1   2   10 
    2   1    1 
       ... and so on... 

La chose est, je aurais besoin tous les deux en une seule requête, parce que sinon j'aurais beaucoup de tri et réarranger pour faire.

Je crois que le deuxième compte, plus facile sur le total des vis par voiture devrait être fait comme une sous-requête, mais puis-je rejoindre la première, plus grande requête facilement avec une sous-requête?

Comment cela est-il fait?

Je serais heureux d'avoir des réponses assez spécifiques, car je ne suis pas vraiment un assistant SQL.

éditer: Je travaille sur un ORM, donc funky pense comme ci-dessous (hacking les valeurs de col à une constante) ne peut pas être fait facilement. Je dois obtenir cette solution fonctionnant là, ainsi JOIN/sous-requête/UNIONs sans solutions de contournement géniales serait génial.

Répondre

1
SELECT car_id, wheel_id, screw_state, count(screws) 
    FROM cars C, wheels W, screws S 
WHERE W.car_id = C.car_id 
    AND S.wheel_id = W.wheel_id 
GROUP BY car_id, wheel_id, screw_state 
UNION ALL 
SELECT car_id, -1 AS wheel_id, screw_state, count(screws) 
    FROM cars C, wheels W, screws S 
WHERE W.car_id = C.car_id 
    AND S.wheel_id = W.wheel_id 
GROUP BY car_id, screw_state 
ORDER BY car_id 

vous pouvez requêtes UNION 2, le second pour toutes les roues par voiture, c'est pourquoi wheel_id = -1.

Résultat:

car_id wheel_id screw_state count(screws) 
     1   1   1   3 
     1   1   2   7 
     1   2   1   5 
     1   2   2   3 
     1   -1   1   8 
     1   -1   2   10 
     2   1   1   1 
     2   -1   1   1 
... 
+0

Testé maintenant, et malheureusement mon serveur MySQL n'aime pas cette syntaxe "-1 wheel_id". J'ai essayé d'écrire wheel_id = -1, cela semble fonctionner, en dehors du fait que dans la sortie, wheel_id sort comme 0 pour le nombre total, au lieu de -1, mais le reste semble fonctionner. – Tom

+0

J'ai utilisé la syntaxe du serveur MS SQL, peut-être pour MySQL, vous devez mettre: -1 comme wheel_id. Je l'ai corrigé dans ma réponse. – manji

+0

SELECT car_id, -1, screw_state, count (vis) fonctionne pour moi – Tom

1

Une recherche rapide indique que MySQL supporte GROUPING SETS. C'est un bon candidat pour cette fonctionnalité:

SELECT car_id, wheel_id, screw_state, count(screws) 
FROM cars C 
JOIN wheels W ON W.car_id = C.car_id 
JOIN screws S ON S.wheel_id = W.wheel_id 
GROUP BY GROUPING SETS (
    (car_id, screw_state, wheel_id), 
    (car_id, screw_state) 
) 
ORDER BY car_id, wheel_id, screw_state 
+1

Bonne idée, mais MySQL ne supporte pas les ensembles de regroupement. Même PostgreSQL vient d'obtenir la fonctionnalité récemment. –

+0

@Seun: Merci de me corriger! J'aurais dû vérifier le manuel MySQL, pas seulement googled et faire confiance à un article aléatoire.[1] [1] http://www.informit.com/articles/article.aspx?p=664143&seqNum=10&rll=1 –

+0

aucun prob, si cela avait fonctionné, votre réponse aurait été mon premier choix, son plus compact et élégant. – Tom