# MySQL/Requêtes

* Introduction
* PhpMyAdmin
* Parcourir les bases de données
* Spécifier les noms
* LDD, LMD et LCD
* Variables utilisateurs
* Alias
* Types de données
* Manipulation de base
** mysqldump
* Manipulation de table
* Manipulation de données
* Requêtes
* NULL
* Opérateurs
* Fonctions
* Procédures stockées
* Regex
* Bases de données spatiales
* Importer et exporter
* Réplication
* Optimisation
* API
* Sécurité
* Mots réservés
* Débogage
* Introduction
* PhpMyAdmin
* Parcourir les bases de données
* Spécifier les noms
* LDD, LMD et LCD
* Variables utilisateurs
* Alias
* Types de données
* Manipulation de base
** mysqldump
* Manipulation de table
* Manipulation de données
* Requêtes
* NULL
* Opérateurs
* Fonctions
* Procédures stockées
* Regex
* Bases de données spatiales
* Importer et exporter
* Réplication
* Optimisation
* API
* Sécurité
* Mots réservés
* Débogage
[ Modifier le sommaire ]

## SELECT

La syntaxe de sélection est la suivante (chaque clause fera l'objet d'un paragraphe explicatif ensuite) :

### Liste de champs

Il faut spécifier les données à récupérer avec SELECT :
L'étoile permet d'obtenir tous les champs d'une table :
Mais il est plutôt conseillé de nommer chaque champ (projection) pour accélérer la requête.

### Noms des tables

Pour récupérer les champs d'une table ou d'une vue, il faut la placer dans la clause FROM :
Autres exemples :

### WHERE

Cette clause permet de filtrer les enregistrements. Prenons pas exemple celui ou ceux dont le champ identifiant est égal à 42 :
Ou bien ceux qui ne sont pas nuls :
Il est impossible d'utiliser le résultat d'une fonction calculée dans le SELECT dans le WHERE, car ce résultat n'est trouvé qu'à la fin de l'exécution, donc WHERE ne peut pas s'en servir au moment prévu.
Pour ce faire il convient d'utiliser HAVING (voir-ensuite)

### GROUP BY

Quand plusieurs enregistrements sont identiques dans le résultat, qu'ils ont les mêmes valeurs dans leurs champs sélectionnés, ils peuvent être groupés en une seule ligne.
Par exemple, en regroupant les enregistrements de la table utilisateurs sur le champ de date d'inscription au wiki, on peut obtenir pour chacune le nombre d'édition maximum, minimum et leurs moyennes :
Idem mais classé par nom et prénom d'utilisateur :
Cette instruction permet donc de réaliser des transpositions lignes en colonnes. Par exemple pour afficher les utilisateurs connus comme ayant le même e-mail :
Si on place le MAX dans le CASE la transposition ne s'effectue pas.
Voir aussi GROUP_CONCAT pour transposer les colonnes en lignes.

#### WITH ROLLUP

Ajouter cette clause à un GROUP BY permet d'ajouter le résultat d'une super-agrégation reprenant l'ensemble des résultats.

### HAVING

HAVING déclare un filtre valable uniquement pour les enregistrements de la clause GROUP BY, ce qui le distingue de WHERE qui lui opère avant GROUP BY.
HAVING n'est pas optimisé et ne peut pas utiliser les index.
Voici un exemple d'erreur d'optimisation classique : l'ordonnancement des opérations ne filtre le gros des résultats (valeur admin) qu'à la fin de la requête (utilisant plus de mémoire, donc plus de temps qu'avec un WHERE) :
Par contre, cet exemple ne peut pas être optimisé car le HAVING utilise le résultat du MAX calculé après le GROUP BY :

### ORDER BY

Il est possible de classer les résultat, par ordre croissant ou décroissant, des nombres ou des lettres.
Par défaut, l'ordre est ASCENDING (croissant). Pour le décroissant il faut donc préciser DESCENDING :
Les valeurs NULL sont considérées comme inférieures aux autres.
Il est également possible de nommer la colonne à classer par son numéro :
Les expressions SQL sont autorisées :
La fonction RAND classe de façon aléatoire :
Quand un GROUP BY est spécifié, les résultats sont classés selon les champs qui y sont nommés, sauf avant un ORDER BY. Donc l'ordre décroissant peut aussi être précisé depuis le GROUP BY :
Pour éviter ce classement automatique du GROUP BY, utiliser ORDER BY NULL :

### LIMIT

Le nombre maximum d'enregistrements dans le résultat est facultatif, on l'indique avec le mot LIMIT :
Ce résultat retourne donc entre 0 et 10 lignes.
Généralement cela s'emploie après un ORDER BY pour avoir les maximums et minimums, mais voici un exemple pour en avoir trois au hasard :
Il est possible de définir une plage d’enregistrements, sachant que le premier est le numéro zéro :
On peut donc paginer les requêtes dont les résultats peuvent saturer le serveur :
La seconde commande est équivalente à celle-ci :
Une astuce consiste à déboguer la syntaxe de sa requête rapidement en lui demandant un résultat vide, et observer ainsi s'il y a des messages d'erreur sans attendre :

#### Conseils d'optimisation

* SQL_CALC_FOUND_ROWS peut accélérer les requêtes.
* LIMIT est particulièrement pratique dans des SELECT avec ORDER BY, DISTINCT et GROUP BY, car leurs calculs n'impliquent pas toutes les lignes.
* Si la requête est résolue par le serveur en copiant les résultats dans une table temporaire, LIMIT aide MySQL à calculer combien de mémoire est requise par la table.

### DISTINCT

Le mot DISTINCT peut être utilisé pour supprimer les doublons des lignes du résultat :
Cela permet par exemple de récupérer la liste de toutes les valeurs différentes d'un champ :
On peut également en sortir les différentes combinaisons de valeurs :
La fonction COUNT a un comportement différent du GROUP BY :
* SELECT COUNT(*) FROM maTable GROUP BY monChamp) : renvoie une ligne pour chaque valeur du champ, avec le nombre d'occurrences dans la table de chacune.
* SELECT COUNT(monChamp) FROM maTable GROUP BY monChamp) : idem mais sans compter les NULL (ils apparaissent avec un total à 0).
* SELECT COUNT(DISTINCT monChamp) FROM maTable : le nombre de valeurs différentes du champ (c'est-à-dire le nombre de lignes des requêtes précédentes).
* SELECT DISTINCT COUNT(*) FROM maTable : le nombre de lignes dans la table.
* SELECT DISTINCT COUNT(monChamp) FROM maTable : le nombre de lignes dans la table sans compter celles où monChamp est NULL.

### IN and NOT IN

Équivalent du signe =, qui ne nécessite pas d'être répété quand il concerne plusieurs valeurs :
Pour améliorer les performances du NOT IN (1, 2), il est généralement préférable d'utiliser NOT EXISTS (select 1, 2).

### EXISTS

Fonction disponible depuis MySQL 4.

### UNION et UNION All

Compatible MySQL 4 et plus. L'union de sélections nécessite qu'elles aient le même nombre de colonnes.
La requête suivante renvoie tous les enregistrements de deux tables :
UNION est équivalent à UNION DISTINCT, ce qui le distingue de UNION ALL qui ne filtre pas les doublons.

## JOIN

Les relations entre les tables permettent de joindre intelligemment leurs résultats. La jointure naturelle est la plus rapide sur la plupart des plateformes SQL.
L'exemple suivant compare les nombres en anglais et en hindi.
| | select * from english | | select * from hindi |
| Tag | Inenglish | Tag | Inhindi |
| 1 | One | 2 | Do |
| 2 | Two | 3 | Teen |
| 3 | Three | 4 | Char |

### INNER JOIN

| Tag | Inenglish | Inhindi |
| 2 | Two | Do |
| 3 | Three | Teen |
La jointure cartésienne décrit le cas où chaque ligne d'une table est jointe à toutes celles d'une autre.
3*3 = 9 lignes :
| Tag | Inenglish | Tag | Inhindi |
| 1 | One | 2 | Do |
| 2 | Two | 2 | Do |
| 3 | Three | 2 | Do |
| 1 | One | 3 | Teen |
| 2 | Two | 3 | Teen |
| 3 | Three | 3 | Teen |
| 1 | One | 4 | Char |
| 2 | Two | 4 | Char |
| 3 | Three | 4 | Char |

### NATURAL JOIN

La jointure naturelle équivaut à INNER JOIN sur toutes les colonnes communes des deux tables.

### USING

Le mot USING est compatible MySQL 4, mais change avec MySQL 5. La requête suivante est équivalente à celles INNER JOIN ci-dessus :

### OUTER JOIN

| Tag | Inenglish | Tag | Inhindi |
| 1 | One | | |
| 2 | Two | 2 | Do |
| 3 | Three | 3 | Teen |
| | | 4 | Char |

### RIGHT OUTER JOIN

* S'assurer que le type des clés de jointes est le même dans les deux tables.
* Les mots clés LEFT et RIGHT ne sont pas absolus, ils opèrent selon le contexte : en intervertissant les tables le résultat sera identique.
* La jointure par défaut est INNER JOIN (pas OUTER).

### FULL OUTER JOIN

MySQL et MariaDB n'ont pas de jointure FULL OUTER JOIN. Voici comment l'émuler :

### Jointures multiples

Il est possible de joindre plus de deux tables :
Exemple :

## Sous requêtes

Compatible MySQL 4.1 et plus.
* Les sous-requêtes SQL permettent aux résultats d'une requête d'être utilisés par une autre.
* Elles apparaissent toujours comme une partie de clause WHERE ou HAVING.
* Seul un champ peut être dans la sous-requête SELECT.
* Les ORDER BY ne sont donc pas autorisés (inutiles sur une seule colonne).
Par exemple, la "table" RepOffice = OfficeNbr from Offices, liste les bureaux où le quota de vente excède la somme des quotas des vendeurs individuels :
??? est la somme des quotas des vendeurs.
En combinant ces deux requêtes, les points d'interrogations disparaissent :
Par exemple, tous les clients avec des commandes ou limites de crédits > 50000 €. En utilisant le mot DISTINCT pour ne lister les clients qu'une seule fois :
* ON : filtre les lignes d'une seule table.
* WHERE : filtre les lignes de toutes les tables.
* HAVING : filtre les lignes de toutes les tables après regroupements.
Les sous-requêtes ne peuvent pas faire référence à un élément de la requête qui les contient. Si c'est nécessaire, il faut les transformer en jointures : ... JOIN (SELECT...) q ON q.id = ...
Exemple :

## References

* ↑ https://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html
* ↑ http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/
* ↑ http://dev.mysql.com/doc/refman/5.0/en/information-functions.html
* ↑ https://stackoverflow.com/questions/173041/not-in-vs-not-exists
* ↑ https://dev.mysql.com/doc/refman/5.7/en/join.html
* ↑ https://mariadb.com/kb/en/with/
* Official MySQL documentation