phpInfo.netLes ArchivesLes éléPHPants

  
  Accueil
  Trucs & Astuces
  Scripts
  Regex
  Annuaire
  Articles

.
      
 Articles   MySQL par l'exemple - L'instruction SELECT  Par Frédéric BOUCHERY   Novembre 2000    »  Rappel
 »  Sélection de champs
 »  Sélection des données en provenance d'une table
 »  Filtrage des données
 »  Jointures
 »  Tris
 »  Regroupements et calculs
 »  Limitation du nombre d'enregistrement
 »  Fonctions de contrôle
 »  Conclusion


Rappel

Avant de commencer, il est bon de rappeller ce qu'est une table dans une base de données.
Une table dans une base de données est un ensemble de lignes de données : les enregistrements.
Chaque donnée possède un nom, c'est le champ.

  idx    prenom    nom  
  1    Gérard    Menvussa  
  2    Alex    Térieur  
  3    Youssouf    Dido  

Dans ce tableau, nous voyons 3 lignes d'enregistrements divisées en 3 champs (colonnes) idx, prenom et nom.



Pour nos exemples, nous utiliserons la table que l'on vient de voir (nommée 'membres') et les 3 tables suivantes (nommées 'messages', 'commandes', 'articles') :

  auteur    texte  
  2    Mon premier message :))  
  1    j'dois dire quoi là ??!  

  idx    commande    article    quantite  
  1    1    1    3  
  2    1    3    1  
  3    2    2    1  
  4    2    1    12  
  5    2    3    2  

  idx    nom    prix  
  1    croissant    0,84  
  2    gateau    16,77  
  3    baguette    0,63  



Si vous voulez afficher le contenu (total ou partiel) d'une table, vous devez demander au serveur MySQL de vous fournir ces informations. Pour cela, on utilise la commande : SELECT.

Sélection de champs

Exemple 1 : SELECT 'Bonjour monde'

Cette commande va nous retourner un seul enregistrement dont le nom du champ est 'Bonjour monde' et dont le contenu est 'Bonjour monde'.

  Bonjour monde  
  Bonjour monde  



Exemple 2 : SELECT 'Bonjour monde' as bonjour

Cette commande nous retourne toujours un enregistrement contenant 'Bonjour monde' mais on en a profité au passage pour renommer le champ en 'bonjour' avec la fonction 'as'.

  bonjour  
  Bonjour monde  



Exemple 3 : SELECT 'Bonjour monde' as 'le bonjour'

Cette fois ci, on a renommer le champ en 'le bonjour', mais comme ce nom contient un espace, on est obligé de l'encadrer par des guillemets.

  le bonjour  
  Bonjour monde  



Exemple 4 : SELECT 'C\'est la date du jour : ' as texte, DATE_FORMAT(NOW(),'%d/%m/%Y') as date

Ici, on affiche 2 champs, le premier étant un texte simple (champ renommé 'texte') et la date du jour mise dans un format plus 'français'.

On peut remarquer 2 choses:
- La présence d'un antislash devant le guillemet afin que l'interpréteur de commande ne considère pas ça comme une fin de chaîne.
- La date retournée est celle du serveur, donc si vous utilisez un serveur à l'étranger, ne vous étonnez pas si l'heure et la date ne correspondent pas à celles de votre machine.

  texte    date  
  C'est la date du jour :     03/11/2000  



Exemple 5 : SELECT CONCAT('Nous sommes le <b>', DATE_FORMAT(NOW(),'%d/%m/%Y'),'</b>') as date

Ici, nous n'avons plus qu'un seul champ, mais nous utilisons la commande 'CONCAT' pour coller les textes ensemble.
Vous pouvez remarquer que nous en profitons pour insérer du code HTML afin de mettre en gras la date.

  date  
  Nous sommes le <b>03/11/2000</b>  

Il est toujours fortement conseillé de renommer les champs avec la fonction 'as' car sinon, celui-ci pourrait vite devenir très long.

Sélection des données en provenance d'une table

Exemple 6 : SELECT nom, prenom FROM membres

Maintenant, les informations proviennent d'une table nommée 'membres'. Les champs 'nom' et 'prenom' sont issus de cette table. Comme il peut exister plusieurs lignes d'enregistrements, nous récupérons non plus une seule ligne comme dans les exemples précédents, mais plusieurs (ou aucune si la table est vide).

  nom    prenom  
  Menvussa    Gérard  
  Térieur    Alex  
  Dido    Youssouf  

Notez que les champs 'nom' et 'prenom' dans la table 'membres' ne sont pas déclarés dans cet ordre.


Exemple 7 : SELECT * FROM membres

Ici, le symbole * indique que nous voulons TOUS les champs de la table.

  idx    prenom    nom  
  1    Menvussa    Gérard  
  2    Térieur    Alex  
  3    Dido    Youssouf  

Nous avons donc TOUS les champs dans l'ordre où ils ont été créés. Vous remarquez bien que 'prenom' est déclaré AVANT 'nom' (cf : remarque de l'exemple précédent)


Exemple 8 : SELECT CONCAT('<a href='whois.php3?idx=',idx,''>',prenom, ' ', nom, '</a>') as membre FROM membres

Ici, nous en profitons pour mettre en forme le texte que l'on va afficher en introduisant directement le code HTML permettant de transformer le couple 'prenom nom' en liens hypertexte donnant des indications sur le membre (trés pratique!).

  membre  
  <a href='whois.php3?idx=1'>Gérard Menvussa</a>  
  <a href='whois.php3?idx=2'>Alex Térieur</a>  
  <a href='whois.php3?idx=3'>Youssouf Dido</a>  


Filtrage des données

Exemple 9 : SELECT CONCAT(prenom, ' ', nom) as membre FROM membres WHERE idx = 3

Dans cette exemple, on ne récupère QUE les lignes d'enregistrements qui répondent aux conditions de la clause 'WHERE'.
Notre table ne contenant qu'un seul enregistrement dont le champ idx est égale à 3, nous avons :

  membre  
  Youssouf Dido  



Exemple 10 : SELECT nom FROM membres WHERE idx = 2 OR prenom LIKE '%a%'

On ne récupère que les lignes d'enregistrements dont le champ idx vaut 2 ou le prénom contient un 'a'.
Une clause 'WHERE' peut contenir un ensemble de conditions, dans notre cas : 2.
La commande 'LIKE' est très utile pour rechercher un texte sans se préoccuper des majuscules/minuscules. De plus, il est possible de mettre des caractères spéciaux '_' (souligné) pour remplacer n'importe quel caractère et '%' pour remplacer de 0 à n caractères (pour plus d'info sur la commande 'LIKE', reportez vous à la documentation de mySQL dans la section 'Fonctions de comparaisons des chaînes').

  nom  
  Menvussa  
  Térieur  


Jointures

Exemple 11 : SELECT membres.nom, membres.prenom, messages.texte FROM membres, messages

Dans cette exemple nous abordons la sélection multi-tables. Comme vous pouvez le constater, nous faisons appelle à 2 tables dans la clause 'FROM', et lorsque nous utilisons un champ, nous précisons le nom de la table.
Le résultat de cette requête peut paraître surprenant :

  nom    prenom    texte  
  Menvussa    Gérard    Mon premier message :))  
  Térieur    Alex    Mon premier message :))  
  Dido    Youssouf    Mon premier message :))  
  Menvussa    Gérard    j'dois dire quoi là ??!  
  Térieur    Alex    j'dois dire quoi là ??!  
  Dido    Youssouf    j'dois dire quoi là ??!  

En fait, on affiche toutes les lignes d'enregistrements de la table membres avec la première ligne d'enregistrements de la table messages, puis toutes les lignes d'enregistrements de la table membres avec la deuxième ligne d'enregistrements de la table messages.
Le nombre total d'enregistrements est calculé comme suit : nombre d'enregistrements de la première table x nombre d'enregistrements de la deuxième tables.
Si on avait inversé dans la clause 'FROM' les tables (... FROM messages, membres nous aurions obtenu le résultat suivant :

  nom    prenom    texte  
  Menvussa    Gérard    Mon premier message :))  
  Menvussa    Gérard    j'dois dire quoi là ??!  
  Térieur    Alex    Mon premier message :))  
  Térieur    Alex    j'dois dire quoi là ??!  
  Dido    Youssouf    Mon premier message :))  
  Dido    Youssouf    j'dois dire quoi là ??!  



Exemple 12 : SELECT a.idx, a.nom, b.auteur, b.texte FROM membres a, messages b

Dans ce nouvel exemple, on renomme les tables en placant le nouveau nom après le nom de la table dans la clause 'FROM'. Il est maintenant possible d'utiliser ces nouveaux noms pour faire référence aux champs. Le code est ainsi racourci.

  idx    nom    auteur    texte  
  1    Menvussa    2    Mon premier message :))  
  2    Térieur    2    Mon premier message :))  
  3    Dido    2    Mon premier message :))  
  1    Menvussa    1    j'dois dire quoi là ??!  
  2    Térieur    1    j'dois dire quoi là ??!  
  3    Dido    1    j'dois dire quoi là ??!  



Exemple 13 : SELECT a.idx,a.nom,b.auteur,b.texte FROM membres a, messages b WHERE a.idx = b.auteur

Le résultat de cette requête nous donne :

  idx    nom    auteur    texte  
  2    Térieur    2    Mon premier message :))  
  1    Menvussa    1    j'dois dire quoi là ??!  

En fait, on n'a gardé que les enregistrements où le champ idx de membres est égal au champ auteur de message (regardez le tableau de l'exemple précédent). Nous venons de réaliser notre première jointure !

'A quoi ça sert ?' me direz-vous. En fait, imaginez notre cas présent, on a une table contenant les membres inscrits. Chaque membre peut laisser un message. On ne va pas créer un enregistrement avec le message et les coordonnées complètes de l'auteur, puisqu'on les a déjà dans la table des membres. On n'enregistre alors que l'index sur la table des membres et lors de l'affichage, on fait ce que l'on appelle une 'jointure' entre nos deux tables.


Exemple 14 : SELECT a.nom, b.texte FROM membres a, messages b WHERE a.idx = b.auteur AND a.idx = 1

Dans cette exemple, on réalise une jointure entre nos deux tables et en plus, on ne veut QUE les messages écrit par le membre 1.

  nom    texte  
  Menvussa    j'dois dire quoi là ??!  



Exemple 15 : SELECT b.texte, a.nom FROM membres a, messages b WHERE a.idx = b.auteur

[Dans cette exemple, on suppose que le membre 1 n'existe plus]

On veut dans cette requête, afficher TOUS les messages de la table 'messages' avec le nom de l'auteur à côté. Ce qui donne :

  texte    nom  
  Mon premier message :))    Térieur  

Le message 'j'dois dire quoi là ??!' n'est pas affiché car le membre 1 n'existe plus dans la base et il est donc impossible de résoudre la jointure 'a.idx = b.auteur' dans le cas de 'auteur = 1'.


Exemple 16 : SELECT b.texte, a.nom FROM messages b LEFT JOIN membres a ON a.idx = b.auteur

[Dans cette exemple, on suppose que le membre 1 n'existe plus]

Ici, on n'utilise plus la jointure par la clause 'WHERE', mais une clause spécifique aux jointures 'LEFT JOIN ... ON ...'.
L'avantage de cette méthode est que si l'on ne trouve pas l'enregistrement correspondant dans la deuxième table, l'enregistrement de la première est malgré tout retourné.

ATTENTION : Les champs correspondants aux enregistrements absents ne sont pas des champs vides, mais des champs nuls.

  texte    nom  
  Mon premier message :))    Térieur  
  j'dois dire quoi là ??!      


Tris

Exemple 17 : SELECT CONCAT(prenom, ' ', nom) as membre FROM membres ORDER BY nom

Ici, on utilise une clause supplémentaire, la clause 'ORDER BY' qui, comme son nom l'indique, permet d'ordonner les lignes d'enregistrements.
Dans cette exemple, on ordonne par le champ 'nom'.

  membre  
  Youssouf Dido  
  Gérard Menvussa  
  Alex Térieur  



Exemple 18 : SELECT CONCAT(prenom, ' ', nom) as membre FROM membres ORDER BY membre DESC

Dans le cas présent, la clause 'ORDER BY' se porte sur le nouveau champ créé 'membre'. De plus, on fait le tri dans l'ordre descendant (DESC). Ce qui est dommage, car on obtient dans notre cas, la même chose que la requête précédente !

  membre  
  Youssouf Dido  
  Gérard Menvussa  
  Alex Térieur  



Exemple 19 : SELECT CONCAT(prenom, ' ', nom) as membre FROM membres ORDER BY prenom ASC, nom DESC

La clause 'ORDER BY' se porte maintenant sur deux champs. Les enregistrements vont donc être triés par les prénoms dans l'ordre ascendant (En fait, ASC n'est pas obligatoire, puisque c'est l'ordre normal d'un tri), et si les prénoms sont identiques, le tri sera fait sur le nom dans l'ordre inverse.

  membre  
  Alex Térieur  
  Gérard Menvussa  
  Youssouf Dido  


Regroupements et calculs

Exemple 20 : SELECT commande, count(*) as 'nombre d\'articles' FROM commandes GROUP BY commande

En fait, la clause 'GROUP BY' s'utilise, dans presque tous les cas, avec des commandes spéciales telles que 'COUNT', 'MAX', 'MIN', SUM', AVG' ... etc.
En fait, quand ces commandes sont utilisées sans la clause 'GROUP BY', elles sont exécutées sur l'ensemble des enregistrements.

  commande    Nombre d'articles  
  1    2  
  2    3  



Exemple 21 : SELECT b.commande, SUM(a.prix * b.quantite) as 'Total (Euros)', CEILING(SUM(a.prix * b.quantite*6.55957)*100)/100 as 'Total (Francs)' FROM commandes b, articles a WHERE a.idx = b.article GROUP BY b.commande

Cette exemple est un peu long, mais il permet d'aborder plusieurs choses :
- Un regroupement avec une somme
- Une jointure
- Des calculs

Plutôt que d'utiliser la commande 'ROUND' pour arrondir à 2 chiffres après la virgule, je fais une multiplication, arrondi et division afin d'arrondir sur 2 décimales au chiffre supérieur. Ben oui ... il faut bien que les euros nous fassent gagner un peu d'argent. ;)

  commande    Total (Euros)    Total (Francs)  
  1    3.15    20.67  
  2    28.11    184.39  


Limitation du nombre d'enregistrement

Exemple 22 : SELECT * FROM membres LIMIT 1,2

Il est arrivé très souvent de devoir limiter le nombre d'enregistrements. Dans cet exemple, on veut les 2 enregistrements commençant à la position 1. Notez que les enregistrements commencent en position 0.

  idx    prenom    nom  
  2    Alex    Térieur  
  3    Youssouf    Dido  

Le cas d'utilisation le plus courant de cette clause, est l'affichage d'informations par pages. Le premier chiffre étant le numéro de la page que multiplie le nombre d'enregistrements par pages et le deuxième chiffre, le nombre d'enregistrements par pages.

Fonctions de contrôle

Exemple 23 : SELECT CONCAT('<option value='',idx,''',IF(idx = 2,' selected',''),'>',nom,'</option>') as opt FROM articles

Voici un bel exemple trés pratique de génération de code HTML directement dans une requête. Ici, on veut générer une liste permettant de choisir un article.
Mais dans une boîte de liste, il y a souvent un élément déjà selectionné, pour cela, on utilise une commande 'IF' afin d'ajouter l'option 'selected' dans le cas où l'article correspond à l'index 2. Si 'idx' est égal à 2, la commande renvoie ' selected' (avec un espace devant) sinon elle renvoie '' (2 guillemets de suite), c'est à dire rien.

  opt  
  <option value='1'>croissant</option>  
  <option value='2' selected>gateau</option>  
  <option value='3'>baguette</option>  



Exemple 24 : SELECT b.texte, IFNULL(a.nom,'(inconnu)') FROM messages b LEFT JOIN membres a ON a.idx = b.auteur

[Dans cette exemple, on suppose que le membre 1 n'existe plus]

J'ai repris l'exemple 16. Dans le cas où l'auteur n'existe pas (le 1), au lieu d'avoir un champ nul, on a le texte '(inconnu)', ce qui est quand même plus explicite ! En fait, la commande 'IFNULL' renvoie le premier argument intact si celui-ci n'est pas nul, sinon elle renvoie le deuxième argument.

  texte    nom  
  Mon premier message :))    Térieur  
  j'dois dire quoi là ??!    (inconnu)  


Conclusion

Cette article ne parle pas de TOUTES les fonctions utilisables dans la commande SELECT, mais aborde les principales.
Je vous invite à lire la documentation sur les fonction utilisées dans les clauses SELECT et WHERE de MySQL (version anglaise, version française).

Ne sous-estimez pas les possibilités des requêtes SELECT, car elles peuvent parfois remplacer un traitement lourd et complexe en PHP.
Synseo