2009-06-03 6 views
14

Quel est le problème avec cette requête:COUNT Mysql (*) sur plusieurs tables

SELECT co.*, mod.COUNT(*) as moduleCount, vid.COUNT(*) as vidCount 
FROM courses as co, modules as mod, videos as vid 
WHERE mod.course_id=co.id AND vid.course_id=co.id ORDER BY co.id DESC 

En d'autres termes, comment puis-je faire si chaque dossier est revenu de « cours », il y a une colonne supplémentaire appelée ' modCount 'qui montre le nombre d'enregistrements dans la table des modules pour ce cours_id, et un autre appelé' vidCount 'qui fait la même chose pour la table des vidéos.

Erreur:

Error Number: 1064

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') as moduleCount, vid.COUNT() as vidCount FROM courses as co, ' at line 1

Répondre

41

à l'aide que vous pouvez faire subselects:

SELECT co.*, 
    (SELECT COUNT(*) FROM modules mod WHERE mod.course_id=co.id) AS moduleCount, 
    (SELECT COUNT(*) FROM videos vid WHERE vid.course_id=co.id) AS vidCount 
FROM courses AS co 
ORDER BY co.id DESC 

Mais attention, car cela est une requête coûteuse lorsque les cours a plusieurs lignes.

EDIT: Si vos tables sont assez grandes la requête suivante devrait effectuer beaucoup mieux (en faveur d'être plus complexe à lire et à comprendre).

SELECT co.*, 
    COALESCE(mod.moduleCount,0) AS moduleCount, 
    COALESCE(vid.vidCount,0) AS vidCount 
FROM courses AS co 
    LEFT JOIN (
      SELECT COUNT(*) AS moduleCount, course_id AS courseId 
      FROM modules 
      GROUP BY course_id 
     ) AS mod 
     ON mod.courseId = co.id 
    LEFT JOIN (
      SELECT COUNT(*) AS vidCount, course_id AS courseId 
      FROM videos 
      GROUP BY course_id 
     ) AS vid 
     ON vid.courseId = co.id 
ORDER BY co.id DESC 
+0

la dépense est une chose importante à garder à l'esprit, en particulier avec plusieurs sous-sélection. – cori

+0

Vous avez une erreur dans votre syntaxe SQL; vérifier le manuel qui correspond à votre version du serveur MySQL pour la bonne syntaxe à utiliser près de 'mod WHERE mod.course_id = co.id) comme moduleCount, (SELECT COUNT (*)' à la ligne 2 –

+0

Il y avait un "O WH" est parti Si cela ne fonctionne pas, votre serveur MySQL ne supporte pas les sous-sélections scalaires Quelle version utilisez-vous? –

2
SELECT co.*, 
     (
     SELECT COUNT(*) 
     FROM modules mod 
     WHERE mod.course_id = co.id 
     ) AS modCount, 
     (
     SELECT COUNT(*) 
     FROM videos vid 
     WHERE vid.course_id = co.id 
     ) AS vidCount 
FROM courses co 
ORDER BY 
     co.id DESC 
1
SELECT co.*, m.ModCnt as moduleCount, v.VidCnt as vidCount 
FROM courses co 
INNER JOIN (
     select count(*) AS ModCnt, co.id AS CoID 
     from modules 
     group by co) m 
    ON m.CoID = co.id 
INNER JOIN (
     select count(*) AS VidCnt, co.id AS CoID 
     from videos 
     group by co) v 
    ON v.CoID = co.id 
INNER JOIN videos vid 
    ON vid.course_id = co.id 
ORDER BY co.id DESC 
+5

Je viens de remarquer cela, modcnt, lol. Êtes-vous autorisé à utiliser 'cnt' comme raccourci dans le code lié au travail? : D –

-2

Shoot this. J'ai fait le travail avec un code non-mysql:

function getAllWithStats($info='*',$order='',$id=0) 
{ 
    $courses=$this->getAll($info,$order,$id); 

    foreach ($courses as $k=>$v) 
    { 
     $courses[$k]['modCount']=$this->getModuleCount($v['id']); 
     $courses[$k]['vidCount']=$this->getVideoCount($v['id']); 
    } 

    return $courses; 
} 
+0

Ceci est essentiellement identique à la solution de sous-sélection. Vous faites deux requêtes supplémentaires pour chaque ligne dans la table des cours, ce qui n'est pas très problématique si la table des cours n'est pas très grande. –

+0

En regardant la solution de sous-sélection et la solution de PHP, il pourrait être intéressant qui fonctionnerait mieux. Même si la solution PHP subira une surcharge de réseau car les données doivent être transmises sur le réseau, la sous-sélection souffrira de l'absence du cache de requête MySQL pour ses sous-sélections - bien que la requête complète soit mise en cache dans le cache de requête. –

10

j'ai une meilleure solution et facile

SELECT COUNT(*),(SELECT COUNT(*) FROM table2) FROM table1 
Questions connexes