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
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.
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'.
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.
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.
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> |
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 :
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').
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à ??! | |
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 |
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 |
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.
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) |
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.
|
|