Poster une réponse 
 
Note de cette discussion :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
[Résolu][SQL] Aide pour construire une requête
Auteur Message
Plume Hors ligne
Membre

Messages : 377
Inscription : Jul 2008
Réputation : 6
Message : #1
[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 armorsplayer_has_armor
WHERE player_has_armor
.players_id $this->playerSess['id']
  AND 
player_has_armor.armors_id armors.id;

SELECT SUM(weapons.weight)
FROM weaponsplayer_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 34

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
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
oxman Hors ligne
Membre

Messages : 749
Inscription : May 2008
Réputation : 10
Message : #2
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 armorsplayer_has_armor
WHERE player_has_armor
.players_id $this->playerSess['id']
  AND 
player_has_armor.armors_id armors.id) +
(
SELECT SUM(weapons.weight)
FROM weaponsplayer_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
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
Sephi-Chan Hors ligne
Administrateur
*******

Messages : 4,492
Inscription : Aug 2006
Message : #3
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    armorsplayers_has_armor
                WHERE    player_has_armor
.players_id $this->playerSess['id']
                AND        
player_has_armor.armors_id armors.id
            
)
            +
            (
                
SELECT    SUM(weapons.weight)
                
FROM    weaponsplayer_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. 4


Sephi-Chan, qui va se coucher, lui aussi…

www.sephi-chan.fr
10-13-2008 12:20 AM
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
Plume Hors ligne
Membre

Messages : 377
Inscription : Jul 2008
Réputation : 6
Message : #4
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
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
Anthor Hors ligne
Membre

Messages : 521
Inscription : Dec 2007
Réputation : 15
Message : #5
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 2

Anthor |
[Image: 352x90.gif]
10-13-2008 11:49 AM
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
Plume Hors ligne
Membre

Messages : 377
Inscription : Jul 2008
Réputation : 6
Message : #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
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
pascal Hors ligne
Membre

Messages : 676
Inscription : Aug 2006
Réputation : 14
Message : #7
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
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
Plume Hors ligne
Membre

Messages : 377
Inscription : Jul 2008
Réputation : 6
Message : #8
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
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
Plume Hors ligne
Membre

Messages : 377
Inscription : Jul 2008
Réputation : 6
Message : #9
RE: [Résolu][SQL] Aide pour construire une requête
Verdict : Ma requête n'était pas bonne. J'la corrige 34

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 ? 11

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
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
Sephi-Chan Hors ligne
Administrateur
*******

Messages : 4,492
Inscription : Aug 2006
Message : #10
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 45) 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
Visiter le site internet de cet utilisateur Trouver tous les messages de cet utilisateur Citer ce message dans une réponse
Poster une réponse 



ContactJeuWeb (JeuPHP) - Crée ton jeu par navigateurRetourner en hautRetourner au contenuVersion bas-débit (Archivé)Syndication RSS