2009-06-03 11 views
14

Co z tego zapytania:Mysql COUNT (*) na wielu stołach

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 

Innymi słowy, w jaki sposób mogę to zrobić tak, ze każdy rekord wrócił z „kursów”, tam dodatkowa kolumna o nazwie " modCount ", który pokazuje liczbę rekordów w tabeli modułów dla tego course id, a drugi nazywa się" vidCount ", co robi to samo dla tabeli filmów.

Błąd:

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

Odpowiedz

41

Korzystanie podselekcji można zrobić:

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 

Ale należy zachować ostrożność, gdyż jest to kosztowne zapytania kiedy kurs ma wiele wierszy.

EDIT: Jeśli tabele są dość duże następujące zapytanie należy wykonać znacznie lepiej (na korzyść bycia bardziej skomplikowane, aby przeczytać i zrozumieć).

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

Koszt to ważna rzecz, o której należy pamiętać, szczególnie w przypadku kilku subselectów. – cori

+0

Wystąpił błąd w składni SQL; sprawdź instrukcję, która odpowiada twojej wersji serwera MySQL dla właściwej składni do użycia w pobliżu 'mod WHERE mod.course_id = co.id) as moduleCount, (SELECT COUNT (*)' w linii 2 –

+0

Zostało "GDZIE" Jeśli to nie zadziała, Twój serwer MySQL nie obsługuje podselekcji skalarnych. Którą wersję używasz? –

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

Właśnie zauważyłem tego modcnt, lol. Czy możesz używać "cnt" jako skrótu w kodzie związanym z pracą? : D –

-2

Zrób to. Zrobiłem zadanie z jakiegoś non-mysql kodu:

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

Jest to zasadniczo takie samo, jak rozwiązanie podselekcji. Robisz dwa dodatkowe zapytania dla każdego wiersza w tabeli kursów, co nie jest bardzo problematyczne, jeśli tabela kursów nie jest zbyt duża. –

+0

Przyglądając się rozwiązaniu podselekcji i rozwiązaniu PHP, może być interesujące, które działałoby lepiej. Mimo że rozwiązanie PHP będzie miało pewien napór sieciowy, ponieważ dane muszą być przesyłane w przewodach, podselekcyjny soltion będzie cierpieć z powodu braku pamięci podręcznej zapytań MySQL dla jego podselekcji - chociaż pełne zapytanie będzie buforowane w pamięci podręcznej zapytań. –

10

mam lepsze rozwiązanie i łatwy

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