Page 1 sur 1

Ordre selection tables

Posté : 08 janv. 2011, 02:16
par devlop78
Bonjour à tous.

La question se trouve à la fin. J'explique toutefois les manipulations effectuées histoire que d'autres critiques ou d'autres idées puissent être postées (sans s'arrêter à la stricte question qui peut vite sortir du contexte).

J'avais déjà fait la malheureuse expérience d'un SELECT FROM a,b,c où mysql effectuait une boucle dans l'odre c,b,a. un peu comme un foreach(c) { foreach (b) { foreach (a) { }}}

Lors d'une jointure, la syntaxe :

SELECT A.id, A.descr, B.name FROM `SUIVI_state_cat` B INNER JOIN SUIVI_state A ON B.id = A.category

Me mets les choses comme "il faut", enfin, par rapport à leur ordre dans la table. Il commence donc bien par les catégories avant les "state" (donc là, de gauche à droite). Si on inverse l'ordre des deux tables : rien ne change. On a donc, comme la documentation le dit, MySQL qui gère sa petite sauce.

Maintenant, je veux que il trie les catégories en fonction d'un champ nommé "order", et les state d'un champs nommé de la même façon.

Evidemment, comme on pouvait s'y attendre si on y réfléchit un temps soit peu, ça ne va pas si on ne contente de mettre après la requête ci dessus un ORDER BY ... Car, c'est bien dans l'ordre, mais si deux catégories ont le même ordre, leurs states sont mélangés dans ces catégories de même ordre.

Pour illustrer, au lieu d'avoir

CAT xx - State 1
CAT xx - State 2
CAT yy - State 1
CAT yy - State 2

On a :

CAT xx - State 1
CAT yy - State 1
CAT xx - State 2
CAT yy - State 2

Et mon but, c'est d'avoir un résultat mySQL prêt à être exploité par Php en le "parsant", sans devoir re-mettre dans le bon ordre. Donc il faut absolument que les State d'une même catégorie soient groupées.

Donc, j'essaie

SELECT A.id, A.descr, B.name FROM (SELECT * FROM `SUIVI_state_cat` ORDER BY `order` ASC) B INNER JOIN
(SELECT * FROM `SUIVI_state` ORDER BY `order` ASC) A
ON B.id = A.category

Ce qui est parfait, en soit. Sauf que ... hébé ... Ca ne marche pas. MySQL décide de commencer par la table des state au lieu des catégories. C'est donc effectivement dans l'ordre, mais pas du tout celui que je voulais. Il me faut donc définir moi-même l'ordre de selection des tables. Au fond, là je lui demande rien de plus que d'effectuer des boucles ...

SELECT STRAIGHT_JOIN A.id, A.descr, B.name FROM (SELECT * FROM `SUIVI_state_cat` ORDER BY `order` ASC) B INNER JOIN
(SELECT * FROM `SUIVI_state` ORDER BY `order` ASC) A
ON B.id = A.category

Paf ... d'après la doc, ce sont les tables les plus à gauche qui sont lues d'abord. Ben ... aucune différence. Par contre, si j'inverse

SELECT STRAIGHT_JOIN A.id, A.descr, B.name FROM (SELECT * FROM `SUIVI_state` ORDER BY `order` ASC) A INNER JOIN
(SELECT * FROM `SUIVI_state_cat` ORDER BY `order` ASC) B
ON B.id = A.category

Magie ! C'est bien ce que je voulais !

Donc, je voudrais être sûr ... quand on dit que Mysql lit de gauche à droite (dans ce cas là, mais ça doit être écrit ailleurs ...), ils sous-entendent que ce sont des arabes qui l'ont fait et que MySQL lit de droit à gauche ?? Sérieusement, ai-je loupé quelque chose ou c'est bien l'ordre droite->gauche ??

Bien cordialement,

Re: Ordre selection tables

Posté : 11 janv. 2011, 19:28
par _devlop78
Problème avec CREATE TRIGGER pour OPTIMIZE : il me dit qu'il retourne des données. J'essaie "CALL OPTIMIZE, EXECUTE OPTIMIZE", mais ça fonctionne pas. D'après la doc de MySQL, il est même possible que OPTIMIZE ne soit pas autorisé dans les triggers.

...

Re: Ordre selection tables

Posté : 17 janv. 2011, 04:40
par devlop78
Pfffff ... Je crois que la solution (non testé encore), sans qu'il soit nécessaire de faire de sous requête est

ORDER BY Cat.order , Cat.id , State.order

J'étais tellement dans un esprit "humain" que j'étais resté bloqué là dessus ...

Cela dit, ma question est toujours valable pour le STRAIGHT_JOIN (j'ai téléchargé le livre SQL pour MySQL, il a l'air assez complet mais n'en parle pas du tout).

Re: Ordre selection tables

Posté : 17 janv. 2011, 11:27
par Mazarini
Bonjour,

Il ne faut pas préjuger de la manière dont MySQL va traiter un select * from a,b,c. En fonction du nombre de lignes dans a, b et c il peut avoir un comportement différent.

Un select * from a,b,c fournit toujours un produit cartésien des 3 tables. C'est la clause where qui permet de sélectionner les lignes que l'on souhaite conserver parmi le produit cartésien. Dans les fait un SGBD ne fait pas le produit cartésien, mais optimise la recherche en fonction des index qu'il peut utilisé et du nombre de ligne.

De même pour connaitre l'ordre de restitution, il faut lui demander par une clause order by.

Re: Ordre selection tables

Posté : 17 janv. 2011, 13:17
par devlop78
De même pour connaitre l'ordre de restitution, il faut lui demander par une clause order by.
Mais, par défaut, il fait l'ordre dans lesquelles elles sont placées sur le disque .. ?? Un SELECT * FROM maTable m'envoie la table dans l'ordre ... et si il pouvait faire ce qu'il veut là dessus, quel serait l'utilité de ALTER TABLE ORDER BY ... ??

Concernant l'ordre de sélection, oui, je l'ai appris à mes dépends. Ma principale question reste pour le STRAIGHT_JOIN. La doc (traduite) dit de Gauche à droite, mais elles sont pourtant en pratique toujours de droite à gauche. Et les autres sites qui en parlent ne font de que simples copier/coller de la doc.

Re: Ordre selection tables

Posté : 17 janv. 2011, 16:02
par Mazarini
Bonjour,

En général l'ordre de restitution est le fruit du hasard, mais 2 requêtes successives donnent généralement le même ordre. La moindre réorganisation de la base est susceptible de changer l'ordre de restitution de même que l'ajout ou la suppression d'enregistrements.

Bref, il faut toujours préciser l'ordre dans lequel on souhaite le résultat.

Pour ce qui est des différents join, j'avoue ne les utiliser que très rarement (left join) à l'exception de requêtes particulières pour lesquels je souhaite avoir les informations même si aucun enregistrement ne correspond dans la seconde table ou pour avoir que les enregistrements sans correspondance. Cela est tellement rare que je suis obligé de consulter la doc à chaque fois.

Re: Ordre selection tables

Posté : 17 janv. 2011, 19:54
par devlop78
Rare ? Moi, j'en ai souvent besoin, et aucune doc n'est nécessaire. Dans toutes mes relations de 1:n, j'en ai besoin. Car, qui dit n, dit potentiellement 0. Ainsi si je souhaite avoir tous les messages avec leurs réponses, il me faut absolument ce left join, sinon aucun message sans réponse ne s'affichera.

C'est peut-être ma technique qui est spéciale, mais je retourne en 1 fois ce que d'autres font en cinquante. Ainsi, j'augmente l'utilisation de la bande passante à la réponse de MySQL, mais je n'exerce qu'une seule requête, donc qu'une compilation, et qu'un allée retour serveur. Après, cela dépend de l'utilisation, c'est une balance à prendre. Pour les catégories par exemple, n'ayant que quelques "State" par catégorie, je préfère renvoyer pour chaque ligne le nom et l'id de la catégorie avec le State, plutot que de récupérer les Categorie, et pour chaque, chercher les states, ou faire deux requetes Categorie/State et regrouper avec plusieurs boucles en Php. Là, une requête, une réponse, et aucun traitement php à faire derrière.

Ainsi je fais

$cat_actuelle = null;

while ($data = mysqli_fetch_array(..)) {

if ($data['id_cat'] != $cat_actuelle) { // On crée le titre de la cat. $cat_actuelle = $data['id_cat']; }

}

C'est ce que j'ai utilisé, ça respecte la séparation Vue/Données et c'est léger. C'est sûr que si j'avais 200 catégories, et 5000 State pour chaque catégorie, je m'orienterais vers des requêtes préparées et/ou un traitement Php.

Concernant l'ordre de restitution, pourrais-tu justifier ta réponse d'une doc ? Car, d'après moi, l'ordre donné est toujours celui de la table, sauf si il y a présence de ORDER BY ou de GROUP BY (ce dernier sans ORDER BY NULL).

Re: Ordre selection tables

Posté : 18 janv. 2011, 17:20
par Mazarini
Concernant l'ordre de restitution des lignes d'une table sans "order by", il est n'y a pas de règle précisé dans les spécifications SQL. De part ce fait chaque SGBD ne prend en compte que des critères de performance pour réaliser l'opération sans se préoccuper de l'ordre.

Si je me rappelle bien la théorie SQL, le résultat d'un select (sans order by) est un ensemble au sens mathématique et tu peux donc en lister les élément dans n'importe quelle ordre sans changer l'ensemble.

Tout ca est très vieux pour moi, mais j'en ai retenu qu'il faut utiliser un order by pour s'assurer de l'ordre.

Concernant le left join, ton utilisation me semble bonne dans le cas 0,n avec affichage des lignes 0 (et des autres). Il se trouve que je suis très rarement dans ce cas sans que je sache pourquoi.
Au passage les "select ... where X in (select...)" sont à proscrire et peuvent justement être remplacé par les left joint voir des jointures classiques. Ca ne m'empêche pas de me laisser aller par moment...

Edit : 1,N veux forcément dire au moins 1, dans le cas contraire, on dit 0,N.

Re: Ordre selection tables

Posté : 18 janv. 2011, 19:30
par devlop78
Edit : 1,N veux forcément dire au moins 1, dans le cas contraire, on dit 0,N.
Je ne parle pas de 1,N mais de 1:1 ou 1:n ou n:n
Après, on peut effectivement définir n appartenant à [1,+infini].

a me fait penser au livre De ULM à SQL que je viens de télé... euhhh, j'avoir :)