Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[MSSQL] Encore plus fort : recuperer le nombre de lien de DEUX tables vers une troisieme.

6 réponses
Avatar
Alex
Hello,

Suite a ma question de la semaine derniere, je me retrouve avec le meme
genre situation avec DEUX tables.

Rappel de la situation :

A :
----
Aid
Aname
Agroup_id_in_C (pointe vers C.Cid)
Agroup_id_in_B (pointe vers B.Bid)

B :
--
Bid
Bname
Bgroup_id_in_C (pointe vers C.Cid)

C :
--
Cid
Cname

Je veux faire un select sur C qui me retourne aussi une colonne contenant le
nombre de A et de B qui pointent vers C.

J'arrive a compter le nombre de A qui pointent vers C ainsi :
SELECT Cid, Cname, count(Aid) FROM C LEFT JOIN A on C.Cid = A.Agroup_id_in_C
GROUP BY Cid, Cname

J'arrive a compter le nombre de B qui pointent vers C ainsi :
SELECT Cid, Cname, count(Bid) FROM C LEFT JOIN B on C.Cid = B.Bgroup_id_in_C
GROUP BY Cid, Cname


Mais ceci ne marche pas :
SELECT Cid, Cname, count(Bid), count(Aid)
FROM C
LEFT JOIN B ON C.Cid = B.Bgroup_id_in_C
LEFT JOIN C ON C.Cid = A.Agroup_id_in_C
GROUP BY Cid, Cname

Ca n'echoue pas, ca me retourne bien deux colonnes de count, mais elles
contiennent la meme chose, qui est en gros le count(Aid).

Comment faire ? suis-je oblige de passer par des sous-requetes ?

Merci beaucoup !
--
Alex
[JDR] Visitez Extremia, un monde gratuit et en francais pour D&D et
autres jeux de role.
www.extremia.org

6 réponses

Avatar
Jogo
Sur fr.comp.applications.sgbd, Alex disait :

Comment faire ? suis-je oblige de passer par des sous-requetes ?



Je pense que oui. En tout cas, on ne peut pas n'utiliser qu'un seul GROUP BY. Il en faut forcement deux, par exemple (pas testé) :

SELECT c.cid, c.cname, coalesce(x.nb,0), coalesce(y.nb,0)
FROM C
LEFT OUTER JOIN (
SELECT Agroup_id_in_C AS cid, count(*) AS nb
FROM A GROUP BY Agroup_id_in_C) X
ON c.cid = x.cid
LEFT OUTER JOIN (
SELECT Bgroup_id_in_C AS cid, count(*) AS nb
FROM B GROUP BY Bgroup_id_in_C) Y
ON c.cid = y.cid

--
Once ... in the wilds of Afghanistan, I lost my corkscrew, and we were
forced to live on nothing but food and water for days.
-- W. C. Fields, "My Little Chickadee"
Avatar
Alex
"Jogo" wrote in message
news:

Je pense que oui. En tout cas, on ne peut pas n'utiliser qu'un seul GROUP
BY. Il en faut forcement deux, par exemple (pas testé) :




Je soupconnais effectivement qu'un seul group by faisait que le regroupement
etait applique aux deux tables, ce qui est incorrect.

SELECT c.cid, c.cname, coalesce(x.nb,0), coalesce(y.nb,0)
FROM C
LEFT OUTER JOIN (
SELECT Agroup_id_in_C AS cid, count(*) AS nb
FROM A GROUP BY Agroup_id_in_C) X
ON c.cid = x.cid
LEFT OUTER JOIN (
SELECT Bgroup_id_in_C AS cid, count(*) AS nb
FROM B GROUP BY Bgroup_id_in_C) Y
ON c.cid = y.cid



Effectivement ca marche comme ca. Je ne connaissais pas coalesce.

Par contre en pratique, apres avoir essaye pour ma culture generale, je suis
tente de rester sur une formulation avec un seul left join et une seule sous
requete du type suivant :
SELECT c.cid, c.cname, count(A.group_id_in_C), (select count(*) from B where
B.group_id_in_C = C.cid)
FROM C
LEFT OUTER JOIN A ON A.group_id_in_C = C.cid
GROUP BY c.cid, c.cname

Je pense que cette formulation est plus legere car il n'u a qu'une
sous-requete, non ?

Merci de m'avoir indique coalesce, en tous cas.
--
Alex
[JDR] Visitez Extremia, un monde gratuit et en francais pour D&D et
autres jeux de role.
www.extremia.org
Avatar
Jogo
Sur fr.comp.applications.sgbd, Alex disait :

SELECT c.cid, c.cname, count(A.group_id_in_C), (select count(*) from
B where B.group_id_in_C = C.cid)
FROM C
LEFT OUTER JOIN A ON A.group_id_in_C = C.cid
GROUP BY c.cid, c.cname

Je pense que cette formulation est plus legere car il n'u a qu'une
sous-requete, non ?



Rien n'est moins sûr. En règle générale, c'est une mauvaise idée de
mettre une sous-requête avant le FROM. Non seulement parce que ce
n'est pas sa place, mais il n'est pas impossible que le planificateur
fasse une sous-requête par ligne de résultat. Bref, ama il n'y a
pas *qu'une* sous-requête dans cette requête.

--
Il y a plus d'un jupon entre la robe et la culotte.
-- Nounou Ogg
Avatar
Alex
"Jogo" wrote in message
news:

Rien n'est moins sûr. En règle générale, c'est une mauvaise idée de
mettre une sous-requête avant le FROM. Non seulement parce que ce
n'est pas sa place, mais il n'est pas impossible que le planificateur
fasse une sous-requête par ligne de résultat. Bref, ama il n'y a
pas *qu'une* sous-requête dans cette requête.



OK, je comprends ce que tu veux dire. C'est bien vu.

Je vais regarder si je vois une difference quelconque entre les deux
methodes a l'usage. Mais comme de toutes facons la charge serveur est
vraiment minime, j'ai peur qu'on ne voie rien en fait.

Merci,
--
Alex
[JDR] Visitez Extremia, un monde gratuit et en francais pour D&D et
autres jeux de role.
www.extremia.org
Avatar
Jogo
Sur fr.comp.applications.sgbd, Alex disait :

Je vais regarder si je vois une difference quelconque entre les deux
methodes a l'usage. Mais comme de toutes facons la charge serveur est
vraiment minime, j'ai peur qu'on ne voie rien en fait.



Il faut que tu vois ce que le planificateur (ou l'ordonnanceur) va
faire de tes requêtes pour pouvoir comparer. Avec pgSQL, il y a la
cmmande EXPLAIN. Pour MSSQL, j'ai trouvé ça :
http://rudi.developpez.com/sqlserver/tutoriel/optimisation/#LI-B

--
Voter [parallélogramme] était permis,
mais seulement le dimanche, si je ne m'abuse.
*- Zelda Touque sur fr.rec.jeux.nomic -*
Avatar
Alex
"Jogo" wrote in message
news:

Il faut que tu vois ce que le planificateur (ou l'ordonnanceur) va
faire de tes requêtes pour pouvoir comparer. Avec pgSQL, il y a la
cmmande EXPLAIN. Pour MSSQL, j'ai trouvé ça :
http://rudi.developpez.com/sqlserver/tutoriel/optimisation/#LI-B



Interessant ! Je vais garder ca sous le coude !

--
Alex
[JDR] Visitez Extremia, un monde gratuit et en francais pour D&D et
autres jeux de role.
www.extremia.org