2016-05-04 10 views
2

Ich habe eine Tabelle, die eine Liste der Klassen an einer Schule enthält. Jede Klasse kann mehrere Sitzungen haben. Und jeder Klasse können Schüler zugewiesen werden.COUNT von verschiedenen Tabellen in GROUP

Was ich tun muss, ist eine Zählung aller Sitzungen für jede Klasse, sowie die Anzahl der Schüler der Klasse zu bekommen. Ich habe das erste Bit gemacht, aber wenn ich mich der Puple-Zuweisungstabelle anschließe, werden meine Zählungen falsch sein.

Ich habe einige falsche SQL heraufbeschworen, die Sie verwenden können.

Ich bin fest mit effizient erhalten eine Zählung von der Pupil Linktabelle.

DECLARE @Class TABLE 
(
    ClassID INT NOT NULL, 
    ClassName VARCHAR(20) NOT NULL 
) 

INSERT INTO @Class VALUES (1, 'English') 
INSERT INTO @Class VALUES (2, 'Maths') 

DECLARE @ClassSession TABLE 
(
    ClassSessionID INT NOT NULL, 
    ClassID INT NOT NULL, 
    Description VARCHAR(100) NOT NULL 
) 

INSERT INTO @ClassSession VALUES (1, 1, 'Basic English') 
INSERT INTO @ClassSession VALUES (2, 1, 'Advanced English') 
INSERT INTO @ClassSession VALUES (3, 1, 'Amazing English') 
INSERT INTO @ClassSession VALUES (4, 2, 'Basic English') 
INSERT INTO @ClassSession VALUES (5, 2, 'Basic English') 

DECLARE @ClassPupil TABLE 
(
    ClassPupilID INT NOT NULL, 
    ClassID INT NOT NULL, 
    PupilID INT NOT NULL -- FK to the Pupils table. 
) 

INSERT INTO @ClassPupil VALUES (1, 1, 1000) 
INSERT INTO @ClassPupil VALUES (2, 1, 1001) 
INSERT INTO @ClassPupil VALUES (3, 1, 1002) 
INSERT INTO @ClassPupil VALUES (4, 1, 1003) 
INSERT INTO @ClassPupil VALUES (5, 1, 1004) 

INSERT INTO @ClassPupil VALUES (6, 2, 1005) 
INSERT INTO @ClassPupil VALUES (7, 2, 1006) 
INSERT INTO @ClassPupil VALUES (8, 2, 1007) 


SELECT ClassName, COUNT(*) AS Sessions, '??' AS NumerOfPupils 
FROM @Class c 
INNER JOIN @ClassSession cs 
ON cs.ClassID = c.ClassID 
GROUP BY c.ClassID, c.ClassName 

Es kann vielleicht mit einer Unterabfrage getan werden? Ist das der beste Weg?

Antwort

2

Sie haben zwei unabhängige Dimensionen für jede Klasse. Sie müssen sie separat aggregat:

SELECT c.ClassName, cs.Sessions, cp.Pupils 
FROM @Class c INNER JOIN 
    (SELECT ClassId, COUNT(*) as sessions 
     FROM @ClassSession cs 
     GROUP BY ClassId 
    ) cs 
    ON cs.ClassID = c.ClassID INNER JOIN 
    (SELECT ClassId, COUNT(*) as pupils 
     FROM @ClassPupil cp 
     GROUP BY ClassId 
    ) cp 
    ON cp.ClassId = c.ClassId; 
2

Eine andere Methode CROSS APPLY zu verwenden ist die Anzahl der Schüler zu erhalten:

SELECT 
    ClassName, COUNT(*) AS Sessions, cp.NumberOfPupils 
FROM @Class c 
INNER JOIN @ClassSession cs 
    ON cs.ClassID = c.ClassID 
CROSS APPLY (
    SELECT COUNT(*) AS NumberOfPupils 
    FROM @ClassPupil 
    WHERE 
     ClassID = c.ClassID 
) cp 
GROUP BY c.ClassID, c.ClassName, cp.NumberOfPupils 
0
SELECT ClassName, COUNT(distinct cs.ClassSessionID) AS Sessions, /*'??'*/ count(distinct cp.PupilID) AS NumerOfPupils 
FROM @Class c 
INNER JOIN @ClassSession cs 
ON cs.ClassID = c.ClassID 
inner join @ClassPupil cp on c.ClassID=cp.ClassID 
GROUP BY /*c.ClassID,*/ c.ClassName 

count (distinct ...) löst (funktioniert um) die Problem.
Im Allgemeinen ist dies (A -> B, C) Problem.