Plume
Membre
Messages : 377
Inscription : Jul 2008
Réputation : 6
|
[Résolu][SQL] Aide pour construire une requête
Plop !
C't'encore mwa ! Content de me revoir - déjà - ?
Cette fois-ci, j'ai cette requête :
Code PHP :
SELECT warehouses.id AS warehouse_id, warehouses.capacityMech, warehouses.capacityWeight, warehouses.countries_id, player_has_warehouse.name AS warehouse_name, // player_has_warehouse.weight, // player_has_warehouse.nb_mechs, countries.name AS country_name FROM player_has_warehouse, warehouses JOIN countries ON warehouses.countries_id = countries.id WHERE player_has_warehouse.players_id = $this->playerSess['id'] AND player_has_warehouse.warehouses_id = warehouses.id
Mon problème, c'est que les données en orange sont des données calculables. Des données que je ne souhaite donc pas avoir en dur dans ma BdD.
Pour avoir ces données, je pourrais faire respectivement :
Code PHP :
SELECT SUM(armors.weight) FROM armors, player_has_armor WHERE player_has_armor.players_id = $this->playerSess['id'] AND player_has_armor.armors_id = armors.id;
SELECT SUM(weapons.weight) FROM weapons, player_has_weapon WHERE player_has_weapon = $this->playerSess['id'] AND player_has_weapon.weapons_id = weapons.id;
J'peux ensuite faire la somme avec une addition PHP et j'ai mon poids.
J'passe ensuite au calcul de la propriété nb_mechs :
Code PHP :
SELECT COUNT(player_has_exomech.id) FROM player_has_exomech WHERE player_has_exomech.players_id = $this->playerSess['id'];
Et j'ai toutes les infos que j'voulais.
Mais j'ai l'intime conviction qu'il est possible de construire une unique requête pour avoir tout ça, sauf qu'à part faire de multiples essais infructueux, j'ai pas la soluce. Et ça fait un ch'ti temps déjà que j'ai pas fait de SQL un peu plus high level. Ca me plait d'ailleurs ces 'tites problématiques
Après, sauf erreur de ma part, j'pense quand même que si une requête n'est pas suffisante, ce p'tit bout d'algo est largement optimisable.
Merci par avance pour le coup de main !
Et maintenant, j'm'en vais me coucher rejoindre ma femme. Ai bien bossé aujourd'hui !
@tchaOo° et bonne nuit !
le Blog de Plume : http://plumeconception.o-n.fr/blog/
(Ce message a été modifié le : 10-13-2008 12:18 PM par Sephi-Chan.)
|
|
| 10-12-2008 11:53 PM |
|
oxman
Membre
Messages : 749
Inscription : May 2008
Réputation : 10
|
RE: Aide pour construire une requête
Code PHP :
SELECT warehouses.id AS warehouse_id, warehouses.capacityMech, warehouses.capacityWeight, warehouses.countries_id, player_has_warehouse.name AS warehouse_name, ((SELECT SUM(armors.weight) FROM armors, player_has_armor WHERE player_has_armor.players_id = $this->playerSess['id'] AND player_has_armor.armors_id = armors.id) + (SELECT SUM(weapons.weight) FROM weapons, player_has_weapon WHERE player_has_weapon = $this->playerSess['id'] AND player_has_weapon.weapons_id = weapons.id)) as weight, (SELECT COUNT(player_has_exomech.id) FROM player_has_exomech WHERE player_has_exomech.players_id = $this->playerSess['id']) as.nb_mechs, countries.name AS country_name FROM player_has_warehouse, warehouses JOIN countries ON warehouses.countries_id = countries.id WHERE player_has_warehouse.players_id = $this->playerSess['id'] AND player_has_warehouse.warehouses_id = warehouses.id
|
|
| 10-13-2008 12:06 AM |
|
Sephi-Chan
Administrateur
      
Messages : 4,492
Inscription : Aug 2006
|
RE: Aide pour construire une requête
La première idée qui me vient est de simplement intégrer les calculs comme des sous-requêtes. Comme cela :
Code PHP :
SELECT warehouses.id AS warehouse_id, warehouses.capacityMech, warehouses.capacityWeight, warehouses.countries_id, player_has_warehouse.name AS warehouse_name, ( ( SELECT SUM(armors.weight) FROM armors, players_has_armor WHERE player_has_armor.players_id = $this->playerSess['id'] AND player_has_armor.armors_id = armors.id ) + ( SELECT SUM(weapons.weight) FROM weapons, player_has_weapon WHERE player_has_weapon = $this->playerSess['id'] AND player_has_weapon.weapons_id = weapons.id ) ) AS weight, ( SELECT COUNT(player_has_exomech.id) FROM player_has_exomech WHERE player_has_exomech.players_id = $this->playerSess['id'] ) AS nb_mechs, countries.name AS country_name FROM player_has_warehouse, warehouses JOIN countries ON warehouses.countries_id = countries.id WHERE player_has_warehouse.players_id = $this->playerSess['id'] AND player_has_warehouse.warehouses_id = warehouses.id;
N'est-il pas plus propre (bien qu'un peu plus verbeux) d'effectuer les jointures explicitement (avec JOIN ON) plutôt que de les faire dans la clause WHERE ?
Par contre, ces informations ont tout intérêt à être mises en cache.
Sephi-Chan, qui va se coucher, lui aussi…
www.sephi-chan.fr
|
|
| 10-13-2008 12:20 AM |
|
Plume
Membre
Messages : 377
Inscription : Jul 2008
Réputation : 6
|
RE: [Resolved] Aide pour construire une requête
Huhu ! Merci les gens ! Encore une fois, c'était plutôt con comme requête.
Pour ce qui est du cache, je verrais quand j'aurais fini quelque chose de fonctionnel. Je ne connais pas les techniques de mises en cache et tout donc j'préfère pas perdre trop de temps, lancer une béta qui sera éprouvée. Pendant cette phase d'épreuve, j'pourrais me pencher sur les optimisations en même temps que les corrections.
Maintenant, j'dis ça mais j'suis ouvert à toutes pistes, propositions,... :]
Encore merci pour le coup de main !
@tchaOo°
[Edit]
J'allais oublié de dire :
Concernant les jointures dans la WHERE Clause, elles sont possibles, elles sont plus simples alors pourquoi s'en priver ?
J'ai cru lire effectivement que quelque part, c'est plus approprié de le faire dans les règles de l'art. Maintenant, si on me convainc du pourquoi du comment, j'suis prêt à faire l'effort. Sans ça, j'vois pas pourquoi je devrais me les casser si j'n'y perds rien ;]
le Blog de Plume : http://plumeconception.o-n.fr/blog/
(Ce message a été modifié le : 10-13-2008 11:47 AM par Plume.)
|
|
| 10-13-2008 11:46 AM |
|
Anthor
Membre
Messages : 521
Inscription : Dec 2007
Réputation : 15
|
RE: [Resolved] Aide pour construire une requête
Ben dans le where, tu obliges le moteur de MySQL à réécrire la requêtes pour y mettre les jointures, c'est tout simple
Anthor |
|
|
| 10-13-2008 11:49 AM |
|
Plume
Membre
Messages : 377
Inscription : Jul 2008
Réputation : 6
|
RE: [Resolved] Aide pour construire une requête
Mouarf ! Il est grand, vu la complexité de la jointure, ça doit pas le mettre à genouxx ?
le Blog de Plume : http://plumeconception.o-n.fr/blog/
|
|
| 10-13-2008 11:53 AM |
|
pascal
Membre
Messages : 676
Inscription : Aug 2006
Réputation : 14
|
RE: [Resolved] Aide pour construire une requête
Plume a écrit :[Edit]
J'allais oublié de dire :
Concernant les jointures dans la WHERE Clause, elles sont possibles, elles sont plus simples alors pourquoi s'en priver ?
J'ai cru lire effectivement que quelque part, c'est plus approprié de le faire dans les règles de l'art. Maintenant, si on me convainc du pourquoi du comment, j'suis prêt à faire l'effort. Sans ça, j'vois pas pourquoi je devrais me les casser si j'n'y perds rien ;]
d'un point de vue syntaxe, c'est plus correct de mettre les jointures via des JOIN, et de les séparer du WHERE.
pourquoi ?
le WHERE représente des conditions, des filtres sur les données, pas des liens entre tables.
Lorsque je fais une requête, je dessine les tables sur papier, avec les liens entre elles (JOIN) et ensuite je m'intéresse aux conditions (WHERE) c'est à dire quelles lignes récupérer.
c'est une question de lisibilité et de convention de programmation.
A+
Pascal
Bonnes pratiques SQL - Passer à la POO
présentation
|
|
| 10-13-2008 12:10 PM |
|
Plume
Membre
Messages : 377
Inscription : Jul 2008
Réputation : 6
|
RE: [Resolved] Aide pour construire une requête
Grumpf !
J'verrais dans l'avenir pour changer mes habitudes. Par contre pas la motivation de revenir sur ce qui est déjà fait ^_^'
Cela dit, j'connais pas beaucoup de monde qui comprenne mieux :
Code PHP :
SELECT * FROM player_has_warehouse, warehouses JOIN countries ON warehouses.countries_id = countries.id JOIN player_has_warehouse ON player_has_warehouse.warehouses_id = warehouses.id WHERE player_has_warehouse.players_id = $this->playerSess['id'];
Plutôt que :
Code PHP :
SELECT * FROM player_has_warehouse, warehouses JOIN countries ON warehouses.countries_id = countries.id WHERE player_has_warehouse.players_id = $this->playerSess['id'] AND player_has_warehouse.warehouses_id = warehouses.id;
En plus, j'suis même pas sûr que ma jointure soit correcte :/
@tchaOo°
le Blog de Plume : http://plumeconception.o-n.fr/blog/
|
|
| 10-13-2008 12:22 PM |
|
Plume
Membre
Messages : 377
Inscription : Jul 2008
Réputation : 6
|
RE: [Résolu][SQL] Aide pour construire une requête
Verdict : Ma requête n'était pas bonne. J'la corrige
Code PHP :
/* SELECT * warehouses.id AS warehouse_id, * warehouses.capacityMech, * warehouses.capacityWeight, * warehouses.countries_id, * player_has_warehouse.name AS warehouse_name, * ( * ( * SELECT SUM(armors.weight) * FROM armors, player_has_armor * WHERE player_has_armor.players_id = $this->playerSess['id'] * AND player_has_armor.armors_id = armors.id * ) * + * ( * SELECT SUM(weapons.weight) * FROM weapons, player_has_weapon * WHERE player_has_weapon = $this->playerSess['id'] * AND player_has_weapon.weapons_id = weapons.id * ) * ) AS weight, * ( * SELECT COUNT(player_has_exomech.id) * FROM player_has_exomech * WHERE player_has_exomech.players_id = $this->playerSess['id'] * ) AS nb_mechs, * countries.name AS country_name * FROM * warehouses * JOIN countries * ON warehouses.countries_id = countries.id * JOIN player_has_warehouse * ON player_has_warehouse.warehouses_id = warehouses.id * WHERE player_has_warehouse.players_id = $this->playerSess['id'] */ $selectWarehouse = 'SELECT ' . ' %s, ' . ' %s, ' . ' %s, ' . ' %s, ' . ' %s, ' . ' ( ' . ' ( ' . ' SELECT SUM(%s) ' . ' FROM %s, %s ' . ' WHERE %s = %d ' . ' AND %s = %s ' . ' ) ' . ' + ' . ' ( ' . ' SELECT SUM(%s) ' . ' FROM %s, %s ' . ' WHERE %s = %d ' . ' AND %s = %s ' . ' ) ' . ' ) AS %s, ' . ' (' . ' SELECT COUNT(%s) ' . ' FROM %s ' . ' WHERE %s = %d ' . ' ) AS %s, ' . ' %s ' . 'FROM %s ' . 'JOIN %s ' . ' ON %s = %s ' . 'JOIN %s' . ' ON %s = %s ' . 'WHERE %s = %d;'; $selectWarehouseQuery = sprintf( $selectWarehouse, $this->tableWarehouses.'.id AS warehouse_id', $this->tableWarehouses.'.capacityMech', $this->tableWarehouses.'.capacityWeight', $this->tableWarehouses.'.countries_id', $this->tablePlayerHasWarehouse.'.name AS warehouse_name', $this->tableArmors.'.weight', $this->tableArmors, $this->tablePlayerHasArmor, $this->tablePlayerHasArmor.'.players_id', $this->playerSess['id'], $this->tablePlayerHasArmor.'.armors_id', $this->tableArmors.'.id', $this->tableWeapons.'.weight', $this->tableWeapons, $this->tablePlayerHasWeapon, $this->tablePlayerHasWeapon.'.players_id', $this->playerSess['id'], $this->tablePlayerHasWeapon.'.weapons_id', $this->tableWeapons.'.id', 'weight', '*', $this->tablePlayerHasExomech, $this->tablePlayerHasExomech.'.players_id', $this->playerSess['id'], 'nb_mechs', $this->tableCountries.'.name AS country_name', $this->tableWarehouses, $this->tableCountries, $this->tableWarehouses.'.countries_id', $this->tableCountries.'.id', $this->tablePlayerHasWarehouse, $this->tablePlayerHasWarehouse.'.warehouses_id', $this->tableWarehouses.'.id', $this->tablePlayerHasWarehouse.'.players_id', $this->playerSess['id'] );
Nice ! Ca tourne et c'est propre, nan ?
le Blog de Plume : http://plumeconception.o-n.fr/blog/
(Ce message a été modifié le : 10-13-2008 12:31 PM par Plume.)
|
|
| 10-13-2008 12:30 PM |
|
Sephi-Chan
Administrateur
      
Messages : 4,492
Inscription : Aug 2006
|
RE: [Résolu][SQL] Aide pour construire une requête
Je pense que rendre constant le nom des tables et des colonnes améliorerait la lisibilité de l'ensemble, les placeholders (ou marques substitutives  ) ont plutôt intérêt à être utilisés pour les paramètres variables.
Si jamais tes noms de table ou de colonnes changent, tu peux au pire lancer un rechercher et remplacer dans ton modèle : ça ne nuit pas à la maintenabilité du projet.
Sephi-Chan
www.sephi-chan.fr
|
|
| 10-13-2008 12:49 PM |
|