Page 1 sur 1

Deux tris selons certains critères

Posté : 24 janv. 2008, 07:13
par Patriboom
Bonjour!

j'ai lu la discussion http://www.phpfrance.com/forums/voir_su ... ris-15.php


qui arrive à la conclusion que ceci fonctionne:
SELECT id_operation, date_debut, date_fin, ecart,
CASE
   WHEN DATEDIFF(date_fin,date_debut) <= 7 THEN "DM"
   WHEN DATEDIFF(date_fin,date_debut) <= 15 THEN "SP"
   WHEN DATEDIFF(date_fin,date_debut) <= 30 THEN "SP"
   ELSE "MS" END
   AS categorie
FROM operations;
Par extension, puis-je utiliser le case dans le tri?
Voici mon cas précis:

J'ai des inscriptions à des cours.
J'ai de profs à donner à chacun des élèves.
J'ai une table d'étudiant qui ressemble à ceci:

CREATE TABLE id_etudiant(VARCHAR), Nom(CHAR), Prenom(CHAR), Date_Naissance(Date)

La table des inscriptions est ainsi:
CREATE TABLE id_inscription(VARCHAR), id_etudiant(VARCHAR), id_prof(VARCHAR), Dte_du_cours(DATE)

Lorsque commence le travail, je dois attribuer un prof aux étudiants inscrit. Chacun a donc, au début du travail une fiche comme ceci:
id_inscription | id_etudiant | id_prof | id_cours | blabla
1 | 901 | 0 | x | blabla
2 | 904 | 0 | x | blabla
3 | 906 | 0 | x | blabla
4 | 902 | 0 | x | blabla
5 | 911 | 0 | x | blabla
6 | 914 | 0 | x | blabla
7 | 916 | 0 | x | blabla
8 | 912 | 0 | x | blabla


En cours de travail, j'attribue un prof à chacun, la table s'enrichie donc en ce sens:
id_inscription | id_etudiant | id_prof | id_cours | blabla
1 | 901 | 2 | x | blabla
2 | 904 | 3 | x | blabla
3 | 906 | 3 | x | blabla
4 | 902 | 0 | x | blabla
5 | 911 | 0 | x | blabla
6 | 914 | 0 | x | blabla
7 | 916 | 0 | x | blabla
8 | 912 | 0 | x | blabla


Pour me faciliter le travail, j'ai besoin de trier les étudiants qui n'ont pas de prof attitrés selon leur date de naissance et le étudiant qui ont un prof attitré selon l'ordre alphabétique de leurs nom et prénom (référant à la table des étudiant par un JOIN LEFT).


Comme faire une requête qui me donne de tels résultats?

Suis-je sur la bonne piste en faisant ainsi:

Code : Tout sélectionner

SELECT PERS.Nom, PERS.Prenom, PROF.Nom, PROF.Prenom FROM table_inscriptions AS INSCR JOIN LEFT table_etudiants AS PERS on PERS.id_etudiant = INSCR.id_etudiant JOIN LEFT table_profs AS PROF on PROF.id_prof=INSCR.id_prof WHERE id_cours = x ORDER BY CASE WHERE INSCR.id_prof = 0 THEN PERS.Date_naissance ASC ELSE PERS.Nom ASC, PERS.Prenom ASC END LIMIT 0, 30
Merci

Posté : 25 janv. 2008, 08:00
par Patriboom
Voici, avec les vraies requêtes, les résultats que j'obtiens:

Code : Tout sélectionner

SELECT PERS.id_perso AS id_perso, CONCAT(PERS.Prenom, " ", PERS.Nom) AS Nom, PERS.Naissance AS Naissance, INSCR.id_inscr, INSCR.id_anim AS ParQui, CONCAT(ANIM.Prenom, " ", ANIM.Nom) AS Animateur FROM paroisses_inscriptions AS INSCR LEFT JOIN paroisses_personnes AS PERS ON PERS.id_perso = INSCR.id_perso LEFT JOIN paroisses_personnes AS ANIM ON ANIM.id_perso = INSCR.id_anim WHERE INSCR.id_acti = 113 AND INSCR.active = 'oui' ORDER BY INSCR.id_anim ASC, PERS.Nom ASC, PERS.Prenom ASC
C'est la requête orginale, qui trie aussi bien les PERS qui ont un prof. que les PERS sans prof.


La première version de modification est celle-ci:

Code : Tout sélectionner

SELECT PERS.id_perso AS id_perso, CONCAT(PERS.Prenom, " ", PERS.Nom) AS Nom, PERS.Naissance AS Naissance, INSCR.id_inscr, INSCR.id_anim AS ParQui, CONCAT(ANIM.Prenom, " ", ANIM.Nom) AS Animateur FROM paroisses_inscriptions AS INSCR LEFT JOIN paroisses_personnes AS PERS ON PERS.id_perso = INSCR.id_perso LEFT JOIN paroisses_personnes AS ANIM ON ANIM.id_perso = INSCR.id_anim WHERE INSCR.id_acti = 113 AND INSCR.active = 'oui' ORDER BY CASE WHEN INSCR.id_anim = 0 PERS.Naissance, PERS.Nom ELSE INSCR.id_anim ASC, PERS.Nom ASC, PERS.Prenom ASC END
Et voici le résultat:
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 'PERS.Naissance , PERS.Nom ELSE INSCR.id_anim ASC , PERS.Nom ASC , PERS.Prenom AS' at line 1


Voici une deuxième version essayée:

Code : Tout sélectionner

SELECT PERS.id_perso AS id_perso, CONCAT(PERS.Prenom, " ", PERS.Nom) AS Nom, PERS.Naissance AS Naissance, INSCR.id_inscr, INSCR.id_anim AS ParQui, CONCAT(ANIM.Prenom, " ", ANIM.Nom) AS Animateur FROM paroisses_inscriptions AS INSCR LEFT JOIN paroisses_personnes AS PERS ON PERS.id_perso = INSCR.id_perso LEFT JOIN paroisses_personnes AS ANIM ON ANIM.id_perso = INSCR.id_anim WHERE INSCR.id_acti = 113 AND INSCR.active = 'oui' CASE WHEN INSCR.id_anim = 0 ORDER BY PERS.Naissance, PERS.Nom ELSE ORDER BY INSCR.id_anim ASC, PERS.Nom ASC, PERS.Prenom ASC END
et son code d'erreur 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 'CASE WHEN INSCR.id_anim = 0 ORDER BY PERS.Naissance , PERS.Nom ELSE ORDER BY INS' at line 1

Il me semble que le premier code d'erreur annonce une proximité de la solution.


Voici une troisième tentative, avec IF, celle-là:

Code : Tout sélectionner

SELECT PERS.id_perso AS id_perso, CONCAT(PERS.Prenom, " ", PERS.Nom) AS Nom, PERS.Naissance AS Naissance, INSCR.id_inscr, INSCR.id_anim AS ParQui, CONCAT(ANIM.Prenom, " ", ANIM.Nom) AS Animateur FROM paroisses_inscriptions AS INSCR LEFT JOIN paroisses_personnes AS PERS ON PERS.id_perso = INSCR.id_perso LEFT JOIN paroisses_personnes AS ANIM ON ANIM.id_perso = INSCR.id_anim WHERE INSCR.id_acti = 113 AND INSCR.active = 'oui' ORDER BY IF (INSCR.id_anim = 0) PERS.Naissance, PERS.Nom ELSE ORDER BY INSCR.id_anim ASC, PERS.Nom ASC, PERS.Prenom ASC END
et son code d'erreur: 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 ') PERS.Naissance , PERS.Nom ELSE ORDER BY INSCR.id_anim ASC , PERS.Nom ASC , PER' at line 1


Et si j'enlève les parenthèses:

Code : Tout sélectionner

SELECT PERS.id_perso AS id_perso, CONCAT(PERS.Prenom, " ", PERS.Nom) AS Nom, PERS.Naissance AS Naissance, INSCR.id_inscr, INSCR.id_anim AS ParQui, CONCAT(ANIM.Prenom, " ", ANIM.Nom) AS Animateur FROM paroisses_inscriptions AS INSCR LEFT JOIN paroisses_personnes AS PERS ON PERS.id_perso = INSCR.id_perso LEFT JOIN paroisses_personnes AS ANIM ON ANIM.id_perso = INSCR.id_anim WHERE INSCR.id_acti = 113 AND INSCR.active = 'oui' ORDER BY IF INSCR.id_anim == 0 THEN PERS.Naissance, PERS.Nom ELSE ORDER BY INSCR.id_anim ASC, PERS.Nom ASC, PERS.Prenom ASC END
et le code d'erreur: #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 'INSCR.id_anim == 0 THEN PERS.Naissance, PERS.Nom ELSE ORDER BY INSCR.id_anim AS' at line 10 (en plus de me dire que la ponctuation n'est pas correcte) avec = ou ==, même résultat.
Avec des accolades pour délimiter les réponses, il n'y a pas de meilleurs résultats.

Quelqu'un aurait d'autres idées?

Merci à l'avance

Posté : 25 janv. 2008, 09:44
par Hubert Roksor
Salut,

Je n'ai que survolé le sujet pour l'instant, mais d'après tes messages d'erreurs voici ce que je peux en dire:
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 'PERS.Naissance , PERS.Nom ELSE INSCR.id_anim ASC , PERS.Nom ASC , PERS.Prenom AS' at line 1
:arrow: Il manque un THEN avant "PERS.NAissance, ..."
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 'CASE WHEN INSCR.id_anim = 0 ORDER BY PERS.Naissance , PERS.Nom ELSE ORDER BY INS' at line 1
:arrow: Tu ne peux pas utiliser CASE de cette façon. Tu ne peux utiliser CASE que là où tu pourrais utiliser le nom d'une colonne. Tu pourrais faire "ORDER BY CASE ..." mais c'est déconseillé. À la place, crée deux colonnes pour ton résultat et utilise ces colonnes pour le tri, par exemple

Code : Tout sélectionner

SELECT PERS.id_perso AS id_perso, CONCAT(PERS.Prenom, ' ', PERS.Nom) AS Nom, PERS.Naissance AS Naissance, INSCR.id_inscr, INSCR.id_anim AS ParQui, CONCAT(ANIM.Prenom, " ", ANIM.Nom) AS Animateur, CASE WHEN INSCR.id_anim = 0 THEN PERS.Naissance ELSE INSCR.id_anim END CASE AS order_by_col FROM paroisses_inscriptions AS INSCR LEFT JOIN paroisses_personnes AS PERS ON PERS.id_perso = INSCR.id_perso LEFT JOIN paroisses_personnes AS ANIM ON ANIM.id_perso = INSCR.id_anim WHERE INSCR.id_acti = 113 AND INSCR.active = 'oui' ORDER BY order_by_col, PERS.Nom, PERS.Prenom
Il me semble que le premier code d'erreur annonce une proximité de la solution.
C'est toujours le cas, si un message te dit qu'il y a une erreur près "XXX" alors cherche l'erreur juste avant "XXX".

Bonne chance ;)

Posté : 25 janv. 2008, 19:48
par Patriboom
Oui, là tu me donnes une bonne idée pour m'en sortir.
Comme tu écris, je vais créer une colonne bidon à partir (order_by_col) d'un champ x pour un tri et la même colonne bidon à partir du champ y pour l'autre tri. Je ferai ensuite le tri sur la colonne bidon. En effet, quel que soit le tri demandé, j'ai besoin du contenu des champs x et y.

J'en redonnerai des nouvelles. Merci pour le tuyau.


---- 30 minutes plus tard ----

Génial ça marche. Il faire attention, cependant. END CASE n'existe pas, c'est seulement END qu'il faut utiliser.

Voici donc la version finale:

Code : Tout sélectionner

SELECT PERS.id_perso AS id_perso, CONCAT(PERS.Prenom, " ", PERS.Nom) AS Nom, PERS.Naissance AS Naissance, INSCR.id_inscr, INSCR.id_anim AS ParQui, CONCAT(ANIM.Prenom, " ", ANIM.Nom) AS Animateur, CASE WHEN INSCR.id_anim = 0 THEN PERS.Naissance ELSE INSCR.id_anim END AS order_by_col FROM paroisses_inscriptions AS INSCR LEFT JOIN paroisses_personnes AS PERS ON PERS.id_perso = INSCR.id_perso LEFT JOIN paroisses_personnes AS ANIM ON ANIM.id_perso = INSCR.id_anim WHERE INSCR.id_acti = 113 AND INSCR.active = 'oui' ORDER BY Animateur ASC, order_by_col ASC, PERS.Nom ASC, PERS.Prenom ASC
Gros merci