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 10/11/2011, 12h20   #1
Membre du Club
 
Homme Frédéric
Inscription : juin 2011
Messages : 52
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Localisation : France

Informations forums :
Inscription : juin 2011
Messages : 52
Points : 52
Points : 52
Par défaut Récupérer tous les enregistrements ayant la valeur max depuis deux tables identiques

Bonjour à tous,

J'ai deux tables identiques (tableCourante et tableArchive) , et j'aimerai récupérer le ou les enregistrements qui ont la meilleure note.

Cette requête fonctionne, mais elle ne me parait pas trop optimisée :

Code :
1
2
3
4
5
6
7
8
 
 
SELECT  * FROM 
    (SELECT  * FROM tableCourante union SELECT  * FROM tableArchive) A
    WHERE note= 
       (SELECT max(note) FROM 
           (SELECT  * FROM tableCourante union SELECT  * FROM tableArchive) B
       )
Il y a t'il une meilleure façon de faire ?

Merci pour votre aide.
Fred_34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/03/2012, 12h05   #2
Membre du Club
 
Homme Frédéric
Inscription : juin 2011
Messages : 52
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Localisation : France

Informations forums :
Inscription : juin 2011
Messages : 52
Points : 52
Points : 52
Entre temps, j'ai modifié cette requête par celle-ci. Je ne sais plus exactement pourquoi, mais elle devait probablement être plus performante.
Code :
1
2
3
4
5
6
7
 
SELECT * FROM 
  (SELECT * FROM tableCourante UNION ALL SELECT * FROM tableArchive) AS A
  WHERE A.note= 
    (SELECT max(note) AS note FROM tableCourante
    UNION ALL SELECT max(note) AS note FROM tableArchive
    ORDER BY note DESC LIMIT 1);
Pour récupérer la valeur min j'ai du la modifier un petit peu :
Code :
1
2
3
4
5
6
7
 
SELECT * FROM 
  (SELECT * FROM tableCourante UNION ALL SELECT * FROM tableArchive) AS A
  WHERE A.note= 
    (SELECT min(note) AS note FROM tableCourante
    UNION ALL SELECT min(note) AS note FROM tableArchive
    ORDER BY (CASE WHEN note IS NULL THEN 1 ELSE 0 END),note ASC LIMIT 1);

Maintenant, si j'ajoute une condition, par exemple récupérer tous les enregistrements ayant la note minimum ou l'UV est 2, ça donne ceci :
Code :
1
2
3
4
5
6
7
8
 
SELECT * FROM 
  (SELECT * FROM tableCourante UNION ALL SELECT * FROM tableArchive) AS A 
  WHERE A.note =
    (SELECT min(note) AS note FROM tableCourante WHERE uv=2
    UNION ALL SELECT min(note) AS note FROM tableArchive WHERE uv=2
    ORDER BY  (CASE WHEN note IS NULL THEN 1 ELSE 0 END),note ASC LIMIT 1)
  AND A.uv=2;
J'ai un peu l'impression de faire n'importe quoi...
Si quelqu'un pouvait me rassurer ou me donner des pistes sur la bonne façon de faire, ça m’arrangerait bien.
Merci.
Fred_34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/03/2012, 12h23   #3
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 11 029
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 : 11 029
Points : 18 328
Points : 18 328
Envoyer un message via MSN à CinePhil
Il faut éviter de relancer la guerre des étoiles !

Quelle est la note maxi des deux tables ?
Code :
1
2
3
4
5
6
7
8
9
SELECT MAX(note) AS note_max
FROM
(
	SELECT note
	FROM tableCourante
	UNION 
	SELECT note
	FROM tableArchive
) u1
Comme on ne fait l'union que sur les notes et pas sur toutes les colonnes, il y aura probablement moins de lignes, UNION supprimant les doublons.

Maintenant, récupérons les lignes de deux tables qui ont cette note_max :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SELECT --les colonnes nécessaires et pas étoile !
FROM
(
	SELECT --les colonnes nécessaires et pas étoile !
	FROM tableCourante
	UNION ALL
	SELECT --les colonnes nécessaires et pas étoile !
	FROM tableArchive
) u2
WHERE note = 
(
	SELECT MAX(note) AS note_max
	FROM
	(
		SELECT note
		FROM tableCourante
		UNION 
		SELECT note
		FROM tableArchive
	) u1
)
Cette fois pour récupérer toutes les lignes ayant la note MAX, il faut bien utiliser UNION ALL pour éviter le dédoublonnage.
Si tu as besoin de savoir de quelle table provient la ligne, tu ajoutes une colonne fictive :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SELECT --les colonnes nécessaires et pas étoile !
FROM
(
	SELECT 'tableCourante' AS Nom_table, --les colonnes nécessaires et pas étoile !
	FROM tableCourante
	UNION ALL
	SELECT 'tableArchive', --les colonnes nécessaires et pas étoile !
	FROM tableArchive
) u2
WHERE note = 
(
	SELECT MAX(note) AS note_max
	FROM
	(
		SELECT note
		FROM tableCourante
		UNION 
		SELECT note
		FROM tableArchive
	) u1
)
__________________
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 22/03/2012, 15h16   #4
Membre du Club
 
Homme Frédéric
Inscription : juin 2011
Messages : 52
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Localisation : France

Informations forums :
Inscription : juin 2011
Messages : 52
Points : 52
Points : 52
Merci pour ta réponse.

Si je modifie ta requête pour ajouter la condition uv=2, ça me donne:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SELECT --les colonnes nécessaires et pas étoile !
FROM
(
	SELECT --les colonnes nécessaires et pas étoile !
	FROM tableCourante
	UNION ALL
	SELECT --les colonnes nécessaires et pas étoile !
	FROM tableArchive
) u2
WHERE note = 
(
	SELECT MAX(note) AS note_max
	FROM
	(
		SELECT note
		FROM tableCourante
		WHERE uv=2
		UNION 
		SELECT note
		FROM tableArchive
		WHERE uv=2
	) u1
)
AND uv=2;
J'ai ajouté "uv=2" à 3 endroits

Est-ce la bonne façon de faire ? Faut-il plutôt utiliser une jointure?

Avec une jointure je suis arrivé à cette requête :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
SELECT --les colonnes nécessaires et pas étoile !
FROM
(
	SELECT --les colonnes nécessaires et pas étoile !
	FROM tableCourante
	UNION ALL
	SELECT --les colonnes nécessaires et pas étoile !
	FROM tableArchive
) u1
RIGHT JOIN 
(
 
SELECT idtable,uv,MAX(note) AS note
	FROM
	(
		SELECT idtable,uv,note
		FROM tableCourante
		UNION 
		SELECT idtable,uv,note
		FROM tableArchive
	) u2  
  WHERE uv=2
)
u3
USING( idtable,note,uv);
Le résultat a l'air correct, mais comme d'habitude comment savoir si c'est la bonne façon de faire...


Citation:
Envoyé par CinePhil Voir le message
Il faut éviter de relancer la guerre des étoiles !
Vaste débat...

Dans certain cas l'emploi de l'étoile est une erreur, par exemple :
Code :
1
2
3
4
5
6
SELECT  * FROM 
    (SELECT  * FROM tableCourante union SELECT  * FROM tableArchive) A
    WHERE note= 
       (SELECT max(note) FROM 
           (SELECT  * FROM tableCourante UNION SELECT  * FROM tableArchive) B
       )
Doit effectivement être corrigée par :
Code :
1
2
3
4
5
6
SELECT  * FROM 
    (SELECT  * FROM tableCourante union SELECT  * FROM tableArchive) A
    WHERE note= 
       (SELECT max(note) FROM 
           (SELECT  note FROM tableCourante UNION SELECT  note FROM tableArchive) B
       )
Par contre, dans un forum, je trouve que remplacer les étoiles restantes par le nom des colonnes que l'on souhaite récupérer alourdirait la requête et donc la compréhension du problème initial.
De plus, dans mon cas particulier, je "map" les enregistrements dans des objets. Comme je ne sais pas à l'avance ce que l'application va utiliser, il faut tout récupérer...
Accessoirement ça me permet aussi de vérifier que la structure d'une table est identique à celle d'un objet.
Fred_34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 06h30.


 
 
 
 
Partenaires

Hébergement Web