Précédent   Forum des professionnels en informatique > Bases de données > MySQL > Requêtes
Requêtes Forum d'entraide sur les requêtes MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 18/11/2010, 23h07   #1
Membre du Club
 
Inscription : juin 2003
Messages : 83
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 83
Points : 47
Points : 47
Par défaut Problème UNION ALL et SUM

Bonsoir,

j'ai un problème qui va finir par avoir ma peau
J'ai découvert hier l'UNION ALL. Parfait. Je l'applique avec succès dans un certain nombre de cas simples mais pas dans le suivant. Explication.

Je souhaite connaitre les points marqués et concédés par les équipes d'une conférence (sport US) durant les finales.
J'ai donc une table match avec pour le score final deux champs : scoredom et scoreext (comme domicile et extérieur).

La désignation du "dom ext" entre les conférences se fait en alternant une année sur 2.
La conférence A joue les finales à domicile pour les finales 1 3 5 ....
La conférence B joue les finales à domicile pour les finales 2 4 6 ....

Je commence par vouloir les points marqués et concédés par les équipes de la conférence A durant les finales (idFinale : 1 par édition). Donc une année sur deux, les points pour seront dans scoredom et une année sur deux dans scoreext.

Req 1: Points marqués PP et concédés PC cas des matchs à "domicile"
Code :
1
2
3
SELECT COUNT( * ) AS Participant, SUM(scoredom) AS PP, SUM(scoreext) AS PC
FROM finale
WHERE MOD(idFinale,2)!=0
Req 2: Points marqués PP et concédés PC cas des matchs à l'"extérieur" (inversion PP et PC et changement du modulo)
Code :
1
2
3
SELECT COUNT( * ) AS Participant, SUM(scoredom) AS PC, SUM(scoreext) AS PP
FROM finale
WHERE MOD(idFinale,2)=0
A ce stade tout va bien. Si je somme les deux résultats c'est parfait.
Je tente donc une UNION ALL en me disant qu'en sommant les PP et les PC, j'aurais mon total correct.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT SUM( Participant ) AS participantSum, SUM(PP), SUM(PC)
FROM
(
	(
		SELECT COUNT( * ) AS Participant, SUM(scoredom) AS PP, SUM(scoreext) AS PC
		FROM finale
		WHERE MOD(idFinale,2)!=0								
	)
	UNION ALL
	(
		SELECT COUNT( * ) AS Participant, SUM(scoredom) AS PC, SUM(scoreext) AS PP
		FROM finale
		WHERE MOD(idFinale,2)=0
	)
) AS CONF1
Et là c'est le drame !

Les PP-PC des deux requêtes ne s'additionnent pas correctement.
En fait, le résultat est l'addition des scoredom et des scoreext sans tenir compte des ALIAS PP et PC.

C'est comme si j'avais fait :
SELECT SUM(scoredom), SUM(scoreext) FROM finale

Donc soit il me manque quelque chose. Soit la SUM dans un UNION ALL fonctionne mal, est mal "propagée" au SELECT qui l'utilise.

Merci pour votre aide,
Cordialement
kileak est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/11/2010, 00h16   #2
Membre Expert
 
Avatar de gene69
 
Inscription : janvier 2006
Messages : 951
Détails du profil
Informations personnelles :
Localisation : France

Informations professionnelles :
Secteur : High Tech - Produits et services télécom et Internet

Informations forums :
Inscription : janvier 2006
Messages : 951
Points : 1 063
Points : 1 063
je suis vraiment étonné que tu n'aies pas d'erreur de syntaxe dans ta derniere requete, union et mysql...

bon sinon
Code :
1
2
3
4
5
6
7
8
 
SELECT 
	COUNT( * ) AS Participant,
	SUM(scoredom) AS PP,
	SUM(scoreext) AS PC,
	SUM(scoredom) +  SUM(scoreext)  AS TT
FROM finale
WHERE MOD(idFinale,2)!=0
ça ne te plais pas?


edit: pour UNION ce qui compte c'est la position des colonnes, pas leur appellation.
__________________
PHP fait nativement la validation d'adresse électronique Vous êtes perdu en PHP? rassurez-vous ici (en)
Utilisez le bouton résolu!
gene69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/11/2010, 00h26   #3
Membre Expert
 
Avatar de gene69
 
Inscription : janvier 2006
Messages : 951
Détails du profil
Informations personnelles :
Localisation : France

Informations professionnelles :
Secteur : High Tech - Produits et services télécom et Internet

Informations forums :
Inscription : janvier 2006
Messages : 951
Points : 1 063
Points : 1 063
qu'on ne se méprenne pas ce que tu appelles participant c'est le nombre de match. en cas de poule unique et tous les matchs joués, on peut déduire facilement le nombre de joueurs différents du nombre de matchs joués à l'aide de l'inverse de la suite géométrique qui va bien, mais c'est quand même plus facile de faire une requête séparée.
__________________
PHP fait nativement la validation d'adresse électronique Vous êtes perdu en PHP? rassurez-vous ici (en)
Utilisez le bouton résolu!
gene69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/11/2010, 09h30   #4
Membre du Club
 
Inscription : juin 2003
Messages : 83
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 83
Points : 47
Points : 47
Citation:
Envoyé par gene69 Voir le message
je suis vraiment étonné que tu n'aies pas d'erreur de syntaxe dans ta derniere requete, union et mysql...

bon sinon
Code :
1
2
3
4
5
6
7
8
 
SELECT 
	COUNT( * ) AS Participant,
	SUM(scoredom) AS PP,
	SUM(scoreext) AS PC,
	SUM(scoredom) +  SUM(scoreext)  AS TT
FROM finale
WHERE MOD(idFinale,2)!=0
ça ne te plais pas?


edit: pour UNION ce qui compte c'est la position des colonnes, pas leur appellation.
Un immense merci.
Ton edit a donné la solution. C'est hallucinant ce truc. J'ai vraiment cherché des heures mais je n'ai pas trouvé cette règle. C'est quand même un peu tordu. Tu donnes un nom (PP ou PC) et il est ignoré. J'ai donc juste interverti les champs et là ça fonctionne !

Moralité :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT SUM( Participant ) AS participantSum, SUM(PP), SUM(PC)
FROM
(
	(
		SELECT COUNT( * ) AS Participant, SUM(scoredom) AS PP, SUM(scoreext) AS PC
		FROM finale
		WHERE MOD(idFinale,2)!=0								
	)
	UNION ALL
	(
		SELECT COUNT( * ) AS Participant, SUM(scoreext) AS PP, SUM(scoredom) AS PC
		FROM finale
		WHERE MOD(idFinale,2)=0
	)
) AS CONF1
==> OK !

La requête ci-dessus a peut être une petite erreur de syntaxe car j'ai simplifié pour le forum mais encore, en regardant, je ne vois pas.

Aurais-tu un site exhaustif sur les finesses (My)SQL ? Je trouve la donc officielle pauvre en exemple.

Encore merci de m'avoir sorti de cette impasse
kileak est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/11/2010, 10h21   #5
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 932
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur d'études en informatique
Secteur : Enseignement

Informations forums :
Inscription : août 2006
Messages : 10 932
Points : 18 121
Points : 18 121
Envoyer un message via MSN à CinePhil
En fait quand tu fais une UNION de deux requêtes, c'est l'alias de la première requête qui compte pour nommer les colonnes de résultat. Les alias de la ou des autres requêtes unies n'ont aucune importance. Il convient donc en effet de bien faire attention à l'ordre des colonnes.
Et je ne pense pas que ce soit spécifique à MySQL.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/11/2010, 11h36   #6
Membre du Club
 
Inscription : juin 2003
Messages : 83
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 83
Points : 47
Points : 47
C'est ce que mes tests m'ont fait comprendre et c'est effectivement surement général à SQL.

Je viens au passage de découvrir la création de variable dans le SELECT.

En effet, vu que mes conférences sont déterminées par le Modulo, lorsque je veux joindre les deux Unions (là je n'ai parlé que de la CONF1 mais il y a l'autre), il me faut un "champ" pour faire mon group by.

Donc j'ai fait dans la 1ère UNION :
Code :
SELECT SUM( Participant ) AS participantSum, SUM(PP), SUM(PC), @CONF:="CONF1" AS CONF
et dans la seconde :
Code :
SELECT SUM( Participant ) AS participantSum, SUM(PP), SUM(PC), @CONF:="CONF2" AS CONF
Au finale, mon UNION ALL global de mes deux premiers UNION ALL (un par CONF) s'écrit :

Code :
1
2
3
4
5
6
7
SELECT participantSum,PP,PC, (PP-PC) AS diff,CONF
FROM (
   ( ...union ALL conf1... )
   UNION ALL
   ( ...union ALL conf2... )
) AS participantTot
GROUP BY CONF
Ca fonctionne

merci pour votre aide (je passe en résolu).
Bonne journée
kileak est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/11/2010, 11h48   #7
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 10 932
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur d'études en informatique
Secteur : Enseignement

Informations forums :
Inscription : août 2006
Messages : 10 932
Points : 18 121
Points : 18 121
Envoyer un message via MSN à CinePhil
Tu n'as même pas besoin de variable !
Tu peux directement faire ceci :
Code :
SELECT SUM( Participant ) AS participantSum, SUM(PP), SUM(PC), 'CONF1' AS CONF
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/11/2010, 14h40   #8
Membre du Club
 
Inscription : juin 2003
Messages : 83
Détails du profil
Informations forums :
Inscription : juin 2003
Messages : 83
Points : 47
Points : 47
Citation:
Envoyé par CinePhil Voir le message
Tu n'as même pas besoin de variable !
Tu peux directement faire ceci :
Code :
SELECT SUM( Participant ) AS participantSum, SUM(PP), SUM(PC), 'CONF1' AS CONF
Enoooooooooooorme

Merci beaucoup (j'ai quand même appris qu'on pouvait jouer avec des variables )
kileak est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 09h38.


 
 
 
 
Partenaires

Hébergement Web