Requête MySQL ne marche pas

Résolu/Fermé
okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023 - 9 sept. 2022 à 11:26
jee pee Messages postés 38404 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 28 septembre 2023 - 16 sept. 2022 à 10:16

Bonjour,

Table personnes :

ID nom cnrps cin

1 Paul 112233 01020304
2 Jack 223344 02030405
3 Okba 334455 03040506
4 Robert 445566 04050607

Table grades :

id_grade grade

1 Directeur_général
2 Directeur
3 Sous_directeur
4 Chef_Service

Table grades_employes :

id_grade_employe id_grade date_grade ID

1 1 01-01-2020 1
2 1 01-01-2020 2
3 2 01-01-2020 3
4 3 01-01-2021 3

Table structures :

id_structure nom_structure

1 Direction_centrale
2 Direction_régionale
3 Bureau
4 Cellule

Table lieux_travail_employes :

id_lieu_travail_employe id_structure date_lieu_travail ID

1 1 01-01-2020 1
2 2 01-01-2020 2
3 2 01-01-2020 3

Je veux que le résultat suivant:

1 Directeur_générale Paul Direction_centrale 112233 01020304
2 Directeur_générale Jack Direction_régionale 223344 02030405
3 Sous_directeur Okba Direction_régionale 334455 03040506

Mais malheureusement le résultat qui affiché est:

3 Sous_directeur Okba Direction_régionale 334455 03040506

Ma reqête est:

SELECT personnes.ID,grade,nom,nom_structure,cnrps,cin
FROM personnes,grades,grades_employes,structures,lieux_travail_employes
WHERE grades.id_grade=grades_employes.id_grade AND personnes.ID=grades_employes.ID AND grades_employes.date_grade=(SELECT MAX(date_grade) FROM personnes,grades,grades_employes WHERE personnes.ID=grades_employes.ID AND    grades.id_grade=grades_employes.id_grade) AND structures.id_structure=lieux_travail_employes.id_structure AND personnes.ID=lieux_travail_employes.ID AND lieux_travail_employes.date_lieu_travail=(SELECT MAX(date_lieu_travail) FROM personnes,structures,lieux_travail_employes WHERE personnes.ID=lieux_travail_employes.ID AND structures.id_structure=lieux_travail_employes.id_structure)

phpMyAdmin 4.9.7

4 réponses

jee pee Messages postés 38404 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 28 septembre 2023 9 088
Modifié le 15 sept. 2022 à 18:20

Je t'avais suggéré de faire un tableau croisé car je pensais que tes liaisons entre les tables n'étaient pas correctes. Mais en fait c'est la conception des noms des données qui n'est pas claire. On peut trouver pour les identifiants clé primaire et clé externe, 2 logiques, un nom ID présent dans chaque table en clé primaire,et un nom id+table en clé externe : personne(id, nom) grade_employe (id, id_personne, id_grade) ou dès le départ donner un nom distinct , le même en clé primaire et clé externe personne(id_personne, nom) grade_employe (id_grdempl, id_personne, id_grade). Toi tu as un mixe, et surtout, ID dans toutes les tables signifie id_personne. Il faut éviter, tu devrais utiliser la seconde méthode de nommage, avec le même nom partout, et un nom clair. Puis les tables grades_employes et lieux_travail_employes, possèdent une clé primaire, surement générée automatiquement, qui ne sert probablement à rien, on pourrait s'en passer.
 

A tester avec un des sous select, où en fait, on n'a pas besoin de la table personne, puisque grades_employes contient l'ID de la personne ce qui est suffisant comme lien

SELECT personnes.ID, grade, nom, nom_structure, cnrps, cin
FROM personnes P, grades G, grades_employes GE, structures S,lieux_travail_employes SE
WHERE grades.id_grade=grades_employes.id_grade
AND personnes.ID=grades_employes.ID
AND structures.id_structure=lieux_travail_employes.id_structure
AND personnes.ID=lieux_travail_employes.ID
AND grades_employes.date_grade = (SELECT MAX(GE2.date_grade) FROM grades_employes as GE2
              WHERE GE2.ID = P.ID)
1
okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023
16 sept. 2022 à 09:37

merci infinitivement,

J'ai changé l'écriture par abréviation et j'ai ajouté la sous-select date des lieux_travail_employes avec la même démarche de grades_employes que tu a écrit et ça marche très bien :)

SELECT P.ID,grade,nom,nom_structure,cnrps,cin
FROM personnes P,grades G,grades_employes GE,structures S,lieux_travail_employes SE
WHERE G.id_grade=GE.id_grade
AND P.ID=GE.ID
AND S.id_structure=SE.id_structure
AND P.ID=SE.ID
AND GE.date_grade = (SELECT MAX(GE2.date_grade) FROM grades_employes as GE2
WHERE GE2.ID = P.ID)
AND SE.date_lieu_travail = (SELECT MAX(SE2.date_lieu_travail) FROM lieux_travail_employes as SE2
WHERE SE2.ID = P.ID)

problème résolu

0
jee pee Messages postés 38404 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 28 septembre 2023 9 088 > okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023
16 sept. 2022 à 10:16

Bien !
 

Plutôt qu’abréviation, c'est un alias. Et comme indiqué plus haut tu devrais revoir tes noms de colonnes,

ID ==> id_personne

1
jee pee Messages postés 38404 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 28 septembre 2023 9 088
Modifié le 9 sept. 2022 à 12:04

Bonjour,

Avec cette syntaxe, quand dans l'une des 5 tables il manque une correspondance, il n'y a a pas de résulat pour les enregistrements correspondants. Il faudrait utiliser des jointures externes (OUTER JOIN).

Pour les sous-select, et distinguer les tables il faudrait des alias sur les tables dans le FROM

FROM personnes as P


et dans le sous select faire référence à la personne, la table des intitulés de grades ne servant à rien

(SELECT MAX(GE2.date_grade) FROM personnes as P2, grades_employes as GE2
WHERE P2.ID=P.ID AND P2.ID=GE2.ID_grade_employe )

pareil pour le lieu de travail


0
okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023
9 sept. 2022 à 12:51

J'ai modifié la requête comme ça:

SELECT P.ID,grade,nom,nom_structure,cnrps,cin
FROM personnes as P,grades,grades_employes,structures,lieux_travail_employes
WHERE grades.id_grade=grades_employes.id_grade AND P.ID=grades_employes.ID AND grades_employes.date_grade=(SELECT MAX(GE2.date_grade) FROM personnes as P2, grades_employes as GE2
WHERE P2.ID=P.ID AND P2.ID=GE2.id_grade_employe ) AND structures.id_structure=lieux_travail_employes.id_structure AND P.ID=lieux_travail_employes.ID AND lieux_travail_employes.date_lieu_travail=(SELECT MAX(GE3.date_lieu_travail) FROM personnes as P3, lieux_travail_employes as GE3
WHERE P3.ID=P.ID AND P3.ID=GE3.id_lieu_travail_employe )

et le résultat est:

1 Directeur_générale Paul Direction_centrale 112233 01020304

C'est où le problème :/

0
jee pee Messages postés 38404 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 28 septembre 2023 9 088
Modifié le 9 sept. 2022 à 13:38

Tu devrais commencer par faire la requete sans les sous-select de dates, pour juste voir le tableau croisé de toutes les tables

par exemple ce test est faux : AND P.ID=grades_employes.ID , ce champ grades_employes.ID  n'est pas l'ID de la personne

0
okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023 > jee pee Messages postés 38404 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 28 septembre 2023
15 sept. 2022 à 16:14

J'ai essayé mais je n'arrive pas à résoudre cette requête,

Quelle est la solution s'il vous plais ?

0
yg_be Messages postés 21805 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 28 septembre 2023 1 382 > okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023
15 sept. 2022 à 16:41

qu'as-tu essayé, quel résultat as-tu obtenu?

0
okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023 > yg_be Messages postés 21805 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 28 septembre 2023
15 sept. 2022 à 17:32

J'ai essayé de faire la requête sans les sous-select de dates pour juste voir le tableau croisé de toutes les tables

SELECT personnes.ID,grade,nom,nom_structure,cnrps,cin
FROM personnes,grades,grades_employes,structures,lieux_travail_employes
WHERE grades.id_grade=grades_employes.id_grade AND personnes.ID=grades_employes.ID AND structures.id_structure=lieux_travail_employes.id_structure AND personnes.ID=lieux_travail_employes.ID

et la résultat est correct comme ça:

1 Directeur_générale Paul Direction_centrale 112233 01020304
2 Directeur_générale Jack Direction_régionale 223344 02030405
3 Sous_directeur Okba Direction_régionale 334455 03040506
3 Chef_Service Okba Direction_régionale 334455 03040506

Mais 'Okba' est en double (c'est normal par ce qu'il a 2 enregistrements de grade et j'ai fais la requête sans sous select de dates).

Et le problème maintenant dans la partie sous-select de date (il doit lire le nom une seule fois on sélectionne la dernière date de grade).

0

Bonjour,

J'ajouterai aux observations déjà faites; Pourquoi 2 tables distinctes pour les cadres et les non-cadres; ça ne sert à rien, et introduit des confusions plutôt qu'autre chose. Mieux vaudrait une seule table avec les fonctions, peut importe le classement, il suffira au moment de saisir les fonctions de faire apparaitre ce à quoi correspond chaque Id.

Bon courage.

0
okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023
9 sept. 2022 à 15:54

Bonjour,

2 tables parce que je cherche l'historisation; chaque passage de grade et chaque modification de lieux de travail seront sauvegardées dans les tables

0
Tessel75 > okbabb Messages postés 57 Date d'inscription samedi 23 avril 2022 Statut Membre Dernière intervention 15 mai 2023
9 sept. 2022 à 17:45

Eh bien alors il te faut une table "Historique" qui fasse la liaison entre la table "Personnels" et la table "Grades"; ce sera bien plus facile. En même temps, elle te permettra de faire des allers et retours entre les personnes et les différents postes occupés, autant en terme de grades que de localisations, que l'inverse, à savoir, en partant des postes et des lieux, pour retrouver qui a occupé tel ou tel poste à tel ou tel moment.

C'est la même problématique  que pour un hôtel. Tu as une table des chambres, une table des clients, et tu construis une table relai entre les deux, pour garder en mémoire qui a occupé une chambre tel jour, et inversement, quelle chambre a occupé tel client tel ou tel jour. Sans une table relai de ce type, tu ne peux pas t'en sortir.

Bon courage.

0
yg_be Messages postés 21805 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 28 septembre 2023 1 382 > Tessel75
14 sept. 2022 à 14:39

La table grades_employes ne suffit-elle pas pour maintenir l'historique?

0