8797 sujets

Développement web côté serveur, CMS

Pages :
Bonjour,

voici ma base mysql
Table Intervention :
Code_inter
Code_client
...

Table Client :
Code_client
Nom
Prénom
...

Je cherche à lister toutes les intervention d'un nom
C'est a dire récupérer le code_client avec le nom sur la table client
et ensuite avec ce code_client récupérer les interventions

telle une poule j'ai pondu ça :


$nom = $_POST["nom"];
$codes = "SELECT code_client FROM client WHERE nom LIKE '$nom'";
$query_Clients = "SELECT * FROM intervention WHERE code_client LIKE '$codes'";
    $result = mysql_query($query_Clients) or die("La requête <BR><PRE>$SQL</PRE>a échoué : ".mysql_error()); 
    $article =mysql_fetch_object($result);
    $result = mysql_query($query_Clients);

Mais mysql n'a pas l'air de bien le digérer et m'affiche le message suivant :

La requête
a échoué : 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 'test''' at line 1

alors en me faisant mal à la tête pour réfléchir Smiley murf , je me dit que si le nom existe plusieurs fois il reçois plusieurs code_client et qu'il ne peut pas rechercher dessus (et la ma tête surchauffe Smiley biggol ...)
Modifié par mokacola (05 Dec 2008 - 23:40)
Pour ma part j'utiliserai qq chose comme ça...


$nom = $_POST["nom"];

$sql = "SELECT * FROM Intervention, Client WHERE Intervention.Code_client = Client.Code_client AND Nom LIKE '".$nom."'";


ou une variante avec les jokers (%)


$nom = $_POST["nom"];

$sql = "SELECT * FROM Intervention, Client WHERE Intervention.Code_client = Client.Code_client AND Nom LIKE '%".$nom."%'";
Salut,

est-ce bien pertinent de lancer la requête avant d'avoir déterminé quel était le code client ?

En tous les cas je ne vois pas de raison d'utiliser le LIKE et j'aurais fait :
<?php
$nom = $_POST["nom"];
$sql = sprintf("SELECT C.Code_client, Nom, Prenom, Code_inter FROM Client C, Intervention I WHERE C.Code_client = I.Code_client AND Nom = '%s'",
mysql_real_escape_string($nom));
$result = mysql_query($sql) or die("La requête <br /><pre>$sql</pre>a échoué : ".mysql_error());
while($row = mysql_fetch_assoc($result)) {
	echo '<p>Code Client : '.$row['Code_client']. ' / Nom : '.$row['Nom'].' / Prénom : '.$row['Prenom'].' / Code Intervention : '.$row['Code_inter']."</p>\n";
}
?>

Concernant le code que tu as essayé quelques remarques :
* comme je te disais il faut remplacer LIKE par = (et si tu utilises LIKE il faut utiliser % ).
* tout l'intérêt d'avoir une clef commune à tes 2 tables permet de ne faire qu'une requête.
* si tu veux en faire 2 de suite il faut d'abord récupérer tous les résultats de la première et dans ta boucle (while ou autre) pour chacun des code_client trouvé il faut lancer une nouvelle requête sur Interventions.
* quand je vois "La requête ... $SQL a échoué" je me dis que soit c'est une erreur d'inattention puisqu'il aurait fallu mettre $query_Clients... soit tu n'as pas compris comment ça fonctionne. Smiley cligne
Modifié par Heyoan (05 Dec 2008 - 14:09)
Dans ce cas pourquoi ne pas faire un requête imbriquée?

$query_Clients = "SELECT * FROM intervention WHERE code_client IN(
   SELECT code_client FROM client WHERE LIKE '%$nom%'
)";

Modifié par matmat (05 Dec 2008 - 14:18)
matmat a écrit :
Dans ce cas pourquoi ne pas faire un requête imbriquée?
+1... si et seulement si on dispose de PHP5 (il me semble que ça ne fonctionne pas en PHP4) et si on n'a pas besoin de récupérer les infos du client. Smiley murf

PS : mais pourquoi LIKE ?
Modifié par Heyoan (05 Dec 2008 - 14:23)
Heyoan

a écrit :
comme je te disais il faut remplacer LIKE par = (et si tu utilises LIKE il faut utiliser % ).

-j'ai effectivement oublié d'ajouter le % pour le nom.

a écrit :
quand je vois "La requête ... $SQL a échoué" je me dis que soit c'est une erreur d'inattention puisqu'il aurait fallu mettre $query_Clients... soit tu n'as pas compris comment ça fonctionne. cligne

-c'est une erreur d'inattention j'ai fais des tests lorsque j'écrivais ma question et je n'ai pas corriger mon copier/coller

a écrit :
est-ce bien pertinent de lancer la requête avant d'avoir déterminé quel était le code client ?

- je pense en être arrivé au même raisonnement que toi en voulant afficher une page qui me liste la table des clients et ensuite une page qui affiche la table des interventions (ce qui est à ma porté Smiley smile ) (est ce que c'est à ca que tu pensé?)

comment on fait apparaitre Heyoan a écrit : ???
Modifié par mokacola (05 Dec 2008 - 15:57)
mokacola a écrit :

-j'ai effectivement oublié d'ajouter le % pour le nom.
Mais je ne comprends toujours pas le LIKE : est-ce bien un nom qui contient $nom que tu cherches ou un nom qui est égal à $nom ?

mokacola a écrit :

- je pense en être arrivé au même raisonnement que toi en voulant afficher une page qui me liste la table des clients et ensuite une page qui affiche la table des interventions (ce qui est à ma porté Smiley smile ) (est ce que c'est à ca que tu pensé?)
Ouip Smiley smile .

mokacola a écrit :

comment on fait apparaitre Heyoan a écrit : ???
En utilisant le bouton "Citer" du message d'Heyoan ou en utilisant [ quote=Heyoan]...[ /quote] (sans espace après les crochets ouvrants)
Hello,

Lorsque l'on veut récupérer des infos "liées" dans deux tables SQL, on fait ce que l'on appelle une jointure.

Je reprends la requête de Heyoan :

SELECT c.Code_client, c.Nom, c.Prenom, i.Code_inter FROM Client c, Intervention i WHERE C.Code_client = I.Code_client AND Nom = '%s'"


En revanche, je pense que tu as un problème au départ, c'est-à-dire dans le modèle de tes tables :

* Une table doit avoir une clé, qui est un champs ou un groupe de champs dont la valeur sera UNIQUE. Le code client, par exemple. Dans ce cas, impossible d'avoir plusieurs clients ayant le même code. C'est généralement sur ces champs que l'on fait les jointures.

* Dans certains cas, il est utile d'avoir une 3ème table qui regroupe les "couples", ici par exemple code_client / code_intervention. Ca permet d'éviter les doublons ou les infos qui n'ont rien à voir (une date d'intervention correspond à une intervention, indépendament du client concerné). Bon là je donne un exemple peut-être faux car je n'ai pas les spécifications de ta base.

Ce sont les bases d'une construction de base relationnelle. Après, il vaut mieux aussi apprendre les bases du langage SQL...

Les requêtes imbriquées sont généralement très consommatrices de ressources et inutiles.
Modifié par mistike (05 Dec 2008 - 16:42)
Salut,

mistike a écrit :

En revanche, je pense que tu as un problème au départ, c'est-à-dire dans le modèle de tes tables :

* Une table doit avoir une clé, qui est un champs ou un groupe de champs dont la valeur sera UNIQUE.
Euh... à priori Code_inter et Code_client sont uniques non ? Smiley rolleyes

mistike a écrit :
Les requêtes imbriquées sont généralement très consommatrices de ressources et inutiles.
+1... sauf que parfois elles sont tout à fait utiles, notamment lorsque la requête n'est pas sur un champ mais sur un regroupement. Un exemple qui vaut ce qu'il vaut :
SELECT champ1, champ2, COUNT(*) as nombre FROM matable
GROUP  BY champ1, champ2 
HAVING COUNT(*) > (SELECT COUNT(*) FROM monautretable) 
ORDER  BY champ1, champ2

Modifié par Heyoan (05 Dec 2008 - 16:58)
Heyoan a écrit :
Salut,

Euh... à priori Code_inter et Code_client sont uniques non ? Smiley rolleyes


Oui normalement, mais j'ai dit ça surtout en rapport avec cette phrase :

a écrit :
je me dit que si le nom existe plusieurs fois il reçois plusieurs code_client et qu'il ne peut pas rechercher dessus


Je t'accorde qu'il parle du champs "nom" et pas du code, mais dans le doute Smiley cligne

+1... sauf que parfois elles sont tout à fait utiles, notamment lorsque la requête n'est pas sur un champ mais sur un regroupement. Un exemple qui vaut ce qu'il vaut :
SELECT champ1, champ2, COUNT(*) as nombre FROM matable
GROUP  BY champ1, champ2 
HAVING COUNT(*) > (SELECT COUNT(*) FROM monautretable) 
ORDER  BY champ1, champ2


Oui, là c'est différent...

Dans le cas de mokacola, je plussoie ta réponse, la solution est dans la notion de jointure.

Je suis souvent étonnée que les développeurs apprennent et connaissent php sur le bout des doigts, mais pas du tout SQL ni le modèle de bases de données relationnelles qui va avec Smiley decu

Et on se retrouve malheureusement souvent avec des sites très bien codés mais très lourds à cause des requêtes pas du tout optimisées, c'est dommage.

Moi je n'y connais à l'inverse pas grand chose en php, mais j'ai dans le cadre du boulot déjà dû débugger des trucs du genre ça, sur des tables de plusieurs centaines de gigas octets (pas en php) :

SELECT * from maTable into monTableau
(
si truc = 'valeur'
alors
(traitement_de_monTableau
sortie_de_boucle)
sinon continue
)

(truc un champs de maTable).

bon ok, c'est de l'extrême Smiley cligne
Modifié par mistike (05 Dec 2008 - 17:57)
Comme tu travailles sur SAP et donc avec quelques milliers de tables contenant parfois plusieurs millions d'enregistrements je comprends que l'optimisation soit essentielle (perso je bosse souvent avec des ERP sur I-Series et dans ce cas je suis pareil).

Pour ce qui est du web la plupart du temps les tables ne sont pas très grandes et donc j'ai tendance à privilégier la lisibilité du code et à ne m'intéresser à l'optimisation que quand les temps de réponse sont mauvais (c'est également vrai pour tous les autres codes - XHTML, CSS, PHP, etc... -). De ce point de vue la requête de matmat à l'avantage d'être très facile à comprendre. Smiley cligne
Modifié par Heyoan (05 Dec 2008 - 18:16)
Slt
le truc c'est que j'ai des nom de clients identique (même famille)
le champ code_client de la table client est bien unique comme le champ code_intervention de la table intervention

J'ai déjà vue sur internet le fait de créer une table de liens entre les champs des tables mais comme j'ai pas bien compris comment le faire et encore moins comment l'exploiter j'essaye de m'en passer.

j'ai essayer le code :
$query_Clients = "SELECT c.Code_client, c.Nom, i.Code_client, i.Code_inter FROM Clients c, Intervention i WHERE c.Code_client = i.Code_client AND Nom = '%nom%'";


j'ai pas de message d'erreur mais rien ne s'affiche.

mais je ne comprend pas comment il pourrait afficher un résultat avec des $row sur 2 tables(en écrivant je me disait qu'il faut pas utiliser $row) mais je ne vois pas quoi d'autre
Je ne crois pas que la réponse soit dans la notion de jointure, une jointure permet de sélectionner des champs depuis deux tables en fonction d'une condition et un mauvais GROUP BY pour rassembler les résultats n'est pas non plus une solution optimal en terme de performance.
<edit>
Pardon, en fait j'ai bien relu et la requête sous forme de jointure marche trés bien en fait!
</edit>

La requête imbriqué c'est une requête en fonction d'une autre, cela n'est pas forcement problématique au niveau des performances, tout dépend des requêtes. Par exemple si la requête qui est dans le IN( ) sort des milliers de résultats ce serat a peu prés (quoique un peu moins ) aussi catastrophique que de faire :
$result = mysql_query("SELECT id_a FROM magrossetable");
while($assoc = mysql_fetch_assoc($result)){
   $sub_result = mysql_query("SELECT * FROM monautretable WHERE id_b=".$assoc['id_a']);
}

Soit 10000 requêtes si 10000 résultats...

Ors là étant donner que la requête qui est dans le IN ne donnera qu'un seul résultat il n'y a pas de problème. La requête imbriqué est donc une très bonne solution pour les requêtes en fonction d'une table de jonction (type id_tablea | id_tableb )

Pour le LIKE, c'est vrai que c'est pas vraiment nécessaire, juste une précaution car on ne sait d'ou vient le $nom, si d'un input ou d'une autre table ni comment il est filtré, ni si sa case correspond à la valeur de la table.
Modifié par matmat (05 Dec 2008 - 18:40)
mokacola a écrit :
Slt
le truc c'est que j'ai des nom de clients identique (même famille)
le champ code_client de la table client est bien unique comme le champ code_intervention de la table intervention


Aucun problème si dans ta table intervention tu utilises bien Code_Client et pas nom.

a écrit :

j'ai essayer le code :
$query_Clients = "SELECT c.Code_client, c.Nom, i.Code_client, i.Code_inter FROM Clients c, Intervention i WHERE c.Code_client = i.Code_client AND Nom = '%nom%'";


j'ai pas de message d'erreur mais rien ne s'affiche.


Attention, en SQL, le % est l'équivalent de *. Si tu mets = dans ta clause WHERE, alors tu cherches une valeur exacte. Si tu souhaites chercher les noms "qui contiennent la chaine truc", alors tu dois utiliser LIKE.

exemple : dans ta table tu as deux clients

- client 1 dont le nom est Dupond
- client 2 dont le nom est Durand

Si tu écris :

SELECT nom FROM client WHERE nom = "Du"; ==> aucun résultat
SELECT nom FROM client WHERE nom = "Durand" ==> un résultat
SELECT nom FROM client WHERE nom LIKE "Du%" ==> deux résultats

Saisis-tu la nuance ?

a écrit :

mais je ne comprend pas comment il pourrait afficher un résultat avec des $row sur 2 tables(en écrivant je me disait qu'il faut pas utiliser $row) mais je ne vois pas quoi d'autre


Là je pêche un peu sur le php, mais bon. Le résultat d'une requête SQL est rangé dans un tableau, il est donc tout à fait possible (et heureusement) que ta requête te retourne plusieurs enregistrements. Tu parcours les différentes lignes renvoyées avec mysql_fetch_array.

Essaye avec :


SELECT c.Code_client, c.Nom, i.Code_inter FROM Clients c, Intervention i WHERE c.Code_client = i.Code_client AND Nom LIKE '%nom%'


Attention, je me demande si tout ça n'est pas case-sensitive (ça dépend de ta base).

Ca devrait te donner le code client avec son nom et son prénom et le code intervention, pour tous les clients dont le nom contient "nom".

Exemple avec un LIKE "uran" :

1 - Durand - Jean - 12354
1 - Durand - Jean - 15483
5 - Tourang - Jacques - 14575
8 - Durand - Pierre - 15483
matmat a écrit :

La requête imbriqué c'est une requête en fonction d'une autre, cela n'est pas forcement problématique au niveau des performances, tout dépend des requêtes. Par exemple si la requête qui est dans le IN( ) sort des milliers de résultats ce serat a peu prés (quoique un peu moins ) aussi catastrophique que de faire :
$result = mysql_query("SELECT id_a FROM magrossetable");
while($assoc = mysql_fetch_assoc($result)){
   $sub_result = mysql_query("SELECT * FROM monautretable WHERE id_b=".$assoc['id_a']);
}


Ors là étant donner que la requête qui est dans le IN ne donnera qu'un seul résultat il n'y a pas de problème. La requête imbriqué est donc une très bonne solution pour les requêtes en fonction d'une table de jonction (type id_tablea | id_tableb )


Oui mais là justement il n'y a pas de table de jonction

a écrit :

Soit 10000 requêtes si 10000 résultats...


Eh oui... Smiley langue
Je profite pour poser une petite question quel est la différence entre :
SELECT c.Code_client, c.Nom, i.Code_client, i.Code_inter FROM Clients c, Intervention i WHERE c.Code_client = i.Code_client AND Nom = '%nom%'"


et

SELECT Clients.Code_client, Clients.Nom, Intervention.Code_client,Intervention.Code_inter 
FROM Clients LEFT JOIN Intervention ON Clients.Code_client = Intervention.Code_client WHERE Clients.Nom LIKE '%nom%'"

?

Pourquoi la première marcherais vu que la table Intervention n'a pas de champs nom donc ne remplie pas les deux conditions du select? C'est pour ça que je comprend pas trop la logique de cette requête mais il y a peut être un truc que j'ai pas pigé.

Si la première marche alors pourquoi des fois utiliser LEFT JOIN et d'autre fois non?
Modifié par matmat (05 Dec 2008 - 18:56)
mistike a écrit :

Oui mais là justement il n'y a pas de table de jonction

En fait je pensais que la table Intervention étais une table de jonction entre Clients et des infos d'une autre table ou on retrouve le Code_inter, il faut avouer qu'une table avec deux champs et deux code ça ressemble fort a une table de jonction sinon a quoi sert elle? D'ailleurs à quoi sert ce Code_inter?

Pour les performances des requêtes imbriquée je suis d'accord avec toi c'est même ce que j'explique. J'ajoute juste que si la requête dans le IN ne sort qu'un ou bien quelques résultats, il n'y pas problème de performances et cela peut être fort utile, bref c'est à utiliser avec précaution.
Modifié par matmat (05 Dec 2008 - 19:11)
matmat a écrit :

Si la première marche alors pourquoi des fois utiliser LEFT JOIN et d'autre fois non?
Dans les 2 il faudrait plutôt $nom à la place de nom et pour la première mettre plutôt Nom LIKE '%$nom%' à la place de Nom = '%nom%' Smiley lol .

Sinon la forme "LEFT JOIN" est la version optimisée mais les 2 sont équivalentes.

Et autresinon je propose qu'on arrête de dériver de la question de mokacola (qui, s'il en a besoin, pourra consulter une foultitude de ressources comme http://dev.mysql.com/doc/ ou http://sqlpro.developpez.com/ ). Smiley cligne
Modifié par Heyoan (05 Dec 2008 - 19:25)
matmat a écrit :
Je profite pour poser une petite question quel est la différence entre :
SELECT c.Code_client, c.Nom, i.Code_client, i.Code_inter FROM Clients c, Intervention i WHERE c.Code_client = i.Code_client AND Nom = '%nom%'"


et

SELECT Clients.Code_client, Clients.Nom, Intervention.Code_client,Intervention.Code_inter 
FROM Clients LEFT JOIN Intervention ON Clients.Code_client = Intervention.Code_client WHERE Clients.Nom LIKE '%nom%'"

?

Pourquoi la première marcherais vu que la table Intervention n'a pas de champs nom donc ne remplie pas les deux conditions du select? C'est pour ça que je comprend pas trop la logique de cette requête mais il y a peut être un truc que j'ai pas pigé.

Si la première marche alors pourquoi des fois utiliser LEFT JOIN et d'autre fois non?


Exact il y a deux erreurs dans la première requête !



SELECT 
c.Code_client, 
c.Nom, 
i.Code_client, 
i.Code_inter 
FROM Clients c, Intervention i 
WHERE c.Code_client = i.Code_client 
AND c.Nom LIKE '%nom%'"


c.Nom au lieu de Nom dans le AND
et LIKE au lieu de =

La sélection sur le nom se fait dans la table Client. Quoi que ça marcherait peut-être quand même, selon les SGBD.

Ta seconde requête est plus correcte, nettement plus propre. Sur deux tables on peut s'en passer, mais dès qu'on part sur des jointures à plusieurs tables, il vaut mieux utiliser LEFT JOIN ou RIGHT JOIN. Ca permet de donner un ordre à la jointure, si tu veux. C'est pas facile à expliquer Smiley murf

Utiliser la clause WHERE pour faire la jointure est une syntaxe plus ancienne, et sémantiquement incorrecte (puisqu'on est sur Alsa :-p ). Une clause WHERE sert à filtrer, pas à faire la jonction entre deux tables. De plus, les SGBD modernes sont plus efficaces sur un JOIN ... ON que sur un WHERE m.machin = t.truc.

Dans la mesure du possible, si on veut faire une jointure, il faut utiliser la clause faite exprès pour ça...

Et puis moi je trouve ça plus lisible Smiley rolleyes

Un cours très bien : http://sqlpro.developpez.com/cours/sqlaz/jointures/

Heyoan a écrit :

Et autresinon je propose qu'on arrête de dériver de la question de mokacola (qui, s'il en a besoin, pourra consulter une foultitude de ressources comme http://dev.mysql.com/doc/ ou http://sqlpro.developpez.com/ ). cligne


Vi t'as raison on est complètement HS Smiley confused
Modifié par mistike (05 Dec 2008 - 19:27)
Pages :