Desembriquer les requetes SQL

Un article de Le wiki de 2 noisettes - noisette.ch.

Ou en attendant le passage à MySQL 4.1.

Beaucoup de reproches sont faits à MySQL de ne pas gérer les requètes imbriquées (les fameuses subqueries).

En attendant sa venue sur nos serveurs, il faut savoir qu'il est tout à fait possible d'exprimer une requète imbriquée au moyen de requète simple.

La doc de MySQL l'explique très bien, inutile de la recopier. http://dev.mysql.com/doc/mysql/en/rewriting-subqueries.html

Mais en plus, on va donner un exemple concret : on a 2 tables et un relations R d'ordre n:m entre elles

Image:2tables ea.png

et on veut selectionner toutes les entrées de "table1" qui sont en relation avec les objets de "table2" dont l'id vaut 1 ET 3

   * avec une requète imbriquée, on arrive à :
SELECT id FROM table1 t1, R WHERE R.table1_id = t1.id AND R.table2_id ALL IN (
  SELECT id FROM table2 WHERE id = 1 OR id = 3
);
   * sans requète imbriquée, sa donne un truc du style :
SELECT id FROM table1 t1, R r1, R r2 WHERE R.table1_id = t1.id 
  AND r1.table2_id = 1 AND r1.table1_id = t1.id 
  AND r2.table2_id = 3 AND r2.table1_id = t1.id;

En gros, il faut introduire un alias de la table de relation par valeur recherchée. Si on voulait le faire de manière plus générique en PHP, on aurait quelque chose du style

$query = "";
$from = "table1 t1";
$i = 1;
foreach($v as $w) {
  $from .= ", R r" . $i . " ";
  $query .= " AND r" . $i . ".table2_id = " . $w . " AND r" . $i . ".table2_id = t1.id ";
  $i++;
}
$query = "SELECT id FROM table1 t1 " . $from . " WHERE " . ereg_replace("^ AND ", "", $query);