J'ai une requête qui ne veux plus fonctionner sous PHP5 ! Sous PHP4, elle fonctionnait très bien ! meme si je me demandais comment MYSQL pouvait s'y retrouver avec ^^
La requête est la suivante :
SELECT marque.idmarque,marque.marque,modele.idmodele,modele.modele,COUNT(voiture.idvoiture) AS total
FROM marque,modele
LEFT JOIN voiture ON voiture.idmarque = marque.idmarque
WHERE marque.idmarque = modele.idmarque
GROUP BY marque.marque,modele.modele
ORDER BY marque.marque,modele.modele ASC
Les tables :
Marque (idmarque / marque)
1 Renault
2 Citroen
3 Peugeot
...
Modele (idmodele / idmarque / modele)
1 1 Clio
2 1 Scenic
3 2 Xsara
4 2 Saxo
5 3 306
...
Voiture (idvoiture / idmarque / idmodele / serie)
1 1 1 Clio 1
2 1 1 Clio 2
3 3 5 306 phase 1
4 3 5 306 phase 2
...
PS : J'ai inclus l'idmarque dans la table voiture pour éviter de faire trop de jointures entre les tables, car il y aura beaucoup d'enregistrements dans cette table... + d'1 million
Voyez vous un problème dans la requête ? car MYSQL me retourne cette erreur :
#1054 - Unknown column 'marque.idmarque' in 'on clause'
Apparemment, MYSQL n'arrive pas à faire de lien entre la table 'marque' et 'voiture' dans le LEFT JOIN. Pourtant sous PHP4, ca fonctionné ^^
Peut être que je dois activer quelque chose dans le php.ini pour que ça fonctionne ?
Ben tu as juste une erreur SQL, ca n'a rien à voir avec la version de PHP.
Et l'erreur est simple : MySQL ne connait pas le champ "marque.idmarque".
Ensuite, il faudrait voir la structure réelle de tes tables et non une explication en francais de ton schéma de base. Genre un dump de phpmyadmin sur la structure des tables.
Tu n'aurais pas une faute d'orthographe sur le nom de ton champ ? (genre il ne serait pas écrit pareil en base et dans la requête).
Donc peut etre que le probleme est lié au CHARSET ?? car maintenant, sous WAMP, j'ai une colonne 'Interclassement' avec 'latin1_swedish_ci' de mentionner dedans.
Sous WAMP5, j'ai fait un test d'importation de la bdd en latin1, en UTF8, mais ça ne change rien. Idem quand je spécifie le format d'importation en MYSQL 4.
La requête affiche toujours la même erreur.
J'ai essayé de renommé la table, puis de la re renommer 'marque'. Ca ne change rien.
C'est bien MYSQL qui n'arrive pas à faire le lien entre la table voiture et marque.
Développeur récurrent, procédural et relationnel. Caustique soupe-au-lait.
Pourquoi limiter à 100 le nombre de marques ? N'oublie pas que la pire des optimisation, c'est celle qui créé des bogues. Si vraiment ça commence à ramer, il sera toujours temps d'optimiser.
Ta requête ne passait plus parce que MySQL 5 ne comprend pas le SQL comme le comprenait MySQL 4. D'ailleurs, je le comprends, le pauvre.
Pour comprendre ce qui se passe, il faut extraire le morceau suivant :
modele LEFT JOIN voiture ON voiture.idmarque = marque.idmarque
L'erreur retournée est parfaitement explicite. Dans ce code, MySQL fait une jointure sur les table modele et voiture. À ce moment, l'interpréteur ne connait aucune autre table. Ainsi la table marque, on connait pas. D'ailleurs, c'est une erreur de faire intervenir la table marque.
En mettant des parenthèse autour des deux tables, tu grille la priorité au left join en forçant la première jointure. Ce qui créé une table dans laquelle la colonne souhaitée dans le on clause existerait. Certes ça marche, mais question performances... j'ai des doutes sérieux.
Je repose les tables à ma convenance (pour faire des essais), et réécrit la requête que tu semble souhaiter. Au fait, dans la table voitures, le champs marque_id est malvenu. À mon avis. Et si vraiment il y a besoin d'optimiser, il faudra se poser les questions à ce moment.
create table marques (
id int(11) NOT NULL auto_increment,
marque varchar(255) default NULL,
primary key (`id`)
) engine='InnoDB' ;
create table modeles
( id int(11) NOT NULL auto_increment
, modele varchar(255) default NULL
, marque_id integer
, primary key (`id`)
, foreign key (marque_id) references marques(id)
) engine='InnoDB' ;
create table voitures
( idint(11) NOT NULL auto_increment
, label varchar(255) default NULL
, modele_id integer
, primary key (`id`)
, foreign key (modele_id) references modeles(id)
) engine='InnoDB' ;
explain
select
marques.id as marque_id
, marques.marque as marque
, modeles.id as modele_id
, modeles.modele as modele
, count(voitures.id) as total
from voitures left join modeles on voitures.modele_id
left join marques on modeles.marque_id
group by marque, modele
order by marque, modele asc ;
Et puis un conseil : du SQL en aveugle, c'est casse-gueule. Tu devrais lire la documentation de MySQL in extenso pour vraiment maîtriser ces arcanes (ce que je suis loin de pouvoir assurer pour moi ;) ).
J'ai oublié de préciser que j'ai toujours utilisé MyISAM comme moteur SQL. Et comme je comptais utiliser FULL TEXT pour faire une recherche au niveau du nom des voitures par exemple, ou au niveau de leurs descriptions, ça ne va pas fonctionner avec InnoDB !
La fonction recherche sur mon site est une fonction principale pour naviguer dessus (50/75% d'utilisation)... un peu comme un moteur de recherche en fait :) Donc, c'est surtout a ce niveau qu'il faut que j'optimise. Je comptais donc utiliser FULL TEXT !
Existe t'il un moyen d'optimiser une recherche via InnoDB ? à l'instar du FULL TEXT avec MyISAM ?
Tu te contredis la : tu dis utiliser MyISAM, et tu veux faire du FULLTEXT.
Et ben justement, le FULLTEXT, c'est dispo avec MyISAM.
Donc je ne vois pas pourquoi tu parles d'innoDB la.
Ensuite, comment faire la même chose que le FULLTEXT en innoDB, ben il existe plusieurs solutions : dupliquer la table en MyISAM, ou créer un algo de recherche.
Sammuel, tout comme Lupus mic, j'utilise beaucoup innodb (ne serait ce que pour les transactions), et pour le moteur de recherche du site, je duplique en fait mes tables en MyISAM avec un FULLTEXT.
Comment ca marche : quand un message est inséré dans mon forum, je l'insert dans une table innodb et je met aussi à jour d'autres tables, le tout dans une transaction. Ensuite, j'insere également le message dans une table MyISAM (et la, si la requete merde, ben elle merde, au pire les recherches du site seront moins précises, mais je perds pas l'intégrité de ma base principale innoDB).
Les raisons de ce choix :
- simplicité de mise en place
- faible cout CPU lors des recherches
- j'ai une petite base de données à la base (sans table dupliquée) et donc ma base n'est pas forcement beaucoup plus grosse avec ces tables dupliquées (la base pour lephpfacile : 100 Mo environ).
PS : cette technique était utilisée par wikipedia il n'y a pas ci longtemps que ca. Eux par contre, ils remplissaient les tables MyISAM toutes les nuits au lieu de les remplir à chaque insertion d'article => leur recherche était moins précise jusqu'à ce que la nuit arrive, mais le lendemain, la recherche donnait tous les résultats possibles.
PPS : les deux techniques sont combinables => tu peux insérer dans la table MyISAM au fur et à mesure et lancer toutes les nuits un script qui calculera le diff entre les deux tables et compléter la table MyISAM.
Développeur récurrent, procédural et relationnel. Caustique soupe-au-lait.
Et pour encore simplifier les choses, et rendre l'opération atomique, on peut imaginer remplir la table MyISAM depuis une procédure stockée appelée via un trigger.