IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Est-ce que je procède correctement ?


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Août 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 17
    Par défaut Est-ce que je procède correctement ?
    Bonjour !!

    Je débarque assez fraichement dans le monde des requêtes SQL...
    Ca fait un bail que je sais faire des requètes de bases, qui ne posent de problème à personne, mais dès qu'on commence à vouloir faire des trucs fun, c'est une autre paire de manches.

    J'aimerai simplement que vous m'indiquiez si ma démarche est correcte, et comment je pourrai éventuellement améliorer ma requête .


    Pour la petite histoire (zappez si vous êtes pressés) : je développe un jeu php (encore un !..) open source (ça c'est moins fréquent) avec Symfony (ça c'est beaucoup plus rare...).

    Je simplifie le problème pour garder l'essentiel (->j'enlève les FK etc...) :

    J'ai une table buildings (des bâtiments), qui sont caractérisés par une id, un type et un niveau. Le type est un entier, ça correspond par exemple à une ferme, une caserne, une mine... Le niveau représente la taille de ce bâtiment.

    Il est possible d'avoir plusieurs bâtiments du même type.

    Un bâtiment ne peut être construit que si certains bâtiments ont été construits et ont atteint un certain niveau. C'est le principe d'un arbre des technologies (-> un graphe valué orienté non cyclique).

    Par exemple, une caserne ne peut être construite que si l'on a un marché de niveau supérieur ou égal à 2 et une forge de niveau supérieur ou égal à 3.

    Ces relations ne sont pas stockées en BD, mais dans des fichiers de config externes.

    Le but de ma requête est de savoir si je peux construire un nouveau bâtiment. Je fournis donc mes conditions à la requête, et elle doit me renvoyer 1 si les conditions sont remplies, et 0 sinon.

    Voici la table pour l'exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    DROP TABLE IF EXISTS `testBuilding`;
    CREATE TABLE `testBuilding` (
      `id` int(11) NOT NULL auto_increment,
      `type` int(11) NOT NULL,
      `level` int(11) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
     
     
     
    INSERT INTO `testBuilding` (`id`, `type`, `level`) VALUES 
    (1, 0, 2),
    (2, 0, 3),
    (3, 1, 4),
    (4, 2, 5),
    (5, 1, 3),
    (6, 0, 2);
    Et voici une requête avec comme conditions : je veux savoir si j'ai
    au moins un bâtiment de type 0 dont le niveau est supérieur ou égal à 2
    ET
    au moins un bâtiment de type 1 dont le niveau est supérieur ou égal à 3.

    Donc pour résumer, je ne veux pas récupérer ces enregistrements, juste savoir si je les ai bien.


    Voici la requête que j'ai créé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT 1
    FROM(
      SELECT COUNT(type) AS total
      FROM (
        SELECT type, MAX(level) as levelMax
        FROM `testBuilding` 
        WHERE type=0 or type=1 Group by type)
      AS temp
      WHERE (type=0 and levelMax>=2) or (type=1 and levelMax>=3))
    AS temp2 
    WHERE total=2
    En fait, je récupère, pour les types qui m'intéressent, les rangées ayant le niveau le plus élevé (je m'assure ainsi de l'unicité des types). Je compte ensuite combien j'en ai qui vérifient mes conditions, et je vérifie que ce total vaut bien le nombre de conditions.


    J'ai l'impression que je me suis pris le choux pour pas grand chose, et qu'il y a moyen de faire beaucoup plus simple. Mais je ne sais pas trop comment...

    J'espère que vous pourrez m'aider .

    Bonne journée !!

    @++

    Piwaï

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Par défaut
    Avant de considérer la partie SQL, je trouve qu'avoir des fichiers de description de l'arbre et générer, pour chaque demande, une requête dynamiquement avec les bonnes combinaisons types/niveaux est fastidieux.

    As tu considéré la création de l'arbre technologique au sein de la base directement ? Comme ça tu pourrais faire des requêtes qui pourront directement lier un bâtiment et l'arbre technologique nécessaire pour sa construction. Ici tu dois interroger ton fichier de config avec ton langage et créer une requête.

    C'est juste une remarque générale, je ne dis pas que ce serait facile ou le bon choix.

  3. #3
    Membre averti
    Inscrit en
    Août 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 17
    Par défaut
    Bonjour,

    Merci pour cette prompte réponse .

    J'ai pris une habitude, je ne sais pas si elle est bonne : les données variables vont dans une bd, les données de configurations vont dans des fichiers de configuration.

    Pour moi, un arbre technologique est clairement une donnée de configuration : même si les choses sont amenées à changer lors des phases de test et d'équilibrage du jeu, par la suite l'arbre ne bouge plus.

    D'autres part, Symfony manipule particulièrement bien les fichiers YAML (c'est comme du xml, mais c'est plus simple à lire et plus rapide à écrire), et la modification de la config est dès lors relativement aisée.

    Toutefois, je ne suis pas contre la possibilité d'intégrer l'arbre des bâtiments à la base de données, si cela permet d'accélérer les calculs et de simplifier les requêtes (j'en profite pour préciser que j'utilise mysql... pour le moment, et probablement passage en postgres plus tard -> il faut donc que mon code sql soit relativement portable)


    Voici donc la table tel que je la vois :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    CREATE TABLE `condition_buildings` (
    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `type_cible` INT NOT NULL ,
    `type_requis` INT NOT NULL ,
    `level_requis` INT NOT NULL
    ) ENGINE = MYISAM ;
    -> 1 enregistrement par condition pour un bâtiment donné.


    Mais dès lors... que devient ma requête pour savoir si je peux construire un bâtiment ?? Je suis un peu perdu .

    Je suppose qu'il faut créer une fonction sql qui prend un type de bâtiment en paramètre et renvoie 1 si je peux construire le bâtiment, et rien ou 0 sinon.
    Je n'aurai plus qu'à appeller cette fonction...

    Mais je vois mal ce que doit contenir cette fonction .

  4. #4
    Membre averti
    Inscrit en
    Août 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 17
    Par défaut
    Je sais pourquoi je l'ai pas fait en SQL au départ ...

    Parce que c'est galère !!

    Je suis en train de me tordre la tête à imaginer la requête... Mais cha veut pas ..

    Pourtant, le principe est vraiment pas compliqué.

    Auriez-vous sous la main des exemples de fonctionnement d'arbre technologiques, histoire que je m'inspire ? Merci d'avance .

    Je suis aussi très friand de toute idée ou solution à mon problème .

    Merci

    @++

    Piwaï

  5. #5
    Membre Expert

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Par défaut
    La table que tu proposes pour décrire les types de batiment requis pour la création d'un nouveau type est pas mal. Du plus ça sera facile à interroger.

    Si on considère une table T_InstanceBatiment qui recense les bâtiments construits dans ton univers (je néglige les informations d'appartenance, de position, ... probablement nécessaires à ton jeu) :

    T_InstanceBatiment :
    Id
    IdType
    Niveau

    ta table de conditions

    T_ConditionTypeBatiment :
    IdTypeCible
    IdTypeRequis
    NiveauRequis

    une table de description des types de batiments :

    T_TypeBatiment
    IdType


    Voici la requête qui donne tous les types constructibles à partir des batiments que tu as dans ton univers.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT *
    FROM T_TypeBatiment
    WHERE NOT EXISTS 
    	(SELECT * FROM T_InstanceBatiment 
    	WHERE NOT EXISTS 
    		(SELECT * FROM T_ConditionTypeBatiment
    		WHERE T_InstanceBatiment.IdType = T_ConditionTypeBatiment.IdTypeRequis 
    		AND T_InstanceBatiment.Niveau = T_ConditionTypeBatiment.NiveauRequis
    		AND T_TypeBatiment = T_ConditionTypeBatiment.IdTypeCible))
    Du moins l'esprit de la requête car ça tombe jamais bien du premier coup sans test. Je l'énonce en français :

    Retourner tous les types de bâtiment pour lesquels il n'existe pas d'instance de batiment qui ne soit pas dans les types/niveau de batiment requis pour le type.

    Comme je le dis c'est pour l'esprit. Il y a sûrement des erreurs car je suis pas assez bon pour pondre des requêtes bonnes d'un coup sur des trucs un peu compliqués. Il manque aussi la notion de joueur qui dirait pour un joueur donné quels types il peut construire. Mais la difficulté n'est pas là, je me suis concentré sur ta demande.

  6. #6
    Membre averti
    Inscrit en
    Août 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 17
    Par défaut
    Merci pour cette réponse, j'apprécie le temps que tu m'accordes.

    J'ai bien pris le temps de réfléchir avant de te répondre..

    La requête ne fonctionne pas, elle ne renvoie rien (après une petite correction : T_TypeBatiment devient T_TypeBatiment.IdType dans la dernière ligne).

    C'est peut-être un problème purement technique, mais il me semble qu'il y a aussi un problème d'ordre logique :

    Tout d'abord, il s'agit de vérifier qu'on est >= et non = à un niveau (m'enfin ça change pas grand chose).
    D'autres part, il faut savoir qu'un bâtiment n'est pas forcement construit. Donc il est possible que T_InstanceBatiment ne renvoie aucune instance de bâtiment, ce qui ne veut pas dire qu'il n'y aucun bâtiment qui ne remplie pas les critères, mais simplement que certains bâtiments n'existent pas encore (donc ils ne remplissent pas les critères).


    Pour faire plus clair(edit : jme demande si c'est vraiment plus clair..), voici la requête tel que je la vois en français :

    Donner tous les types de bâtiments tel que pour chaque type, toutes les conditions soient remplies. Une condition est remplie lorsque le type_requis existe dans la table des instances de bâtiment (sachant qu'il peut y avoir plusieurs plusieurs bâtiments de même type), et que son level est supérieur ou égal au level_requis.

    Ou encore : donner les types de bâtiment pour lequels il n'existe pas de condition non remplie.

    Reste plus qu'à trouver comment obtenir des conditions non remplies pour un type donné...

    Une condition est non remplie si le batiment type_requis n'existe pas, ou s'il existe et que son niveau est inférieur au niveau requis

    Ca carbure à fond je suis en train de trouver je pense..

    (je fais plein d'édits successifs).

  7. #7
    Membre Expert

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Par défaut
    Citation Envoyé par Piwaï[INSA]
    ...Ou encore : donner les types de bâtiment pour lequels il n'existe pas de condition non remplie.
    ...
    C'est exactement ce que je voulais dire dans :

    Retourner tous les types de bâtiment pour lesquels il n'existe pas d'instance de batiment qui ne soit pas dans les types/niveau de batiment requis pour le type.
    sauf que je détaille le "pas de condition remplie" et que je ne m'exprime pas clairement .


    Ma requête visait cet énoncé mais du premier coup sans avoir de base et de données pour tester, c'est tendu.

  8. #8
    Membre averti
    Inscrit en
    Août 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 17
    Par défaut
    Bon, j'ai pris le temps de bien faire les choses.

    Il ne me manque plus qu'une petite réponse pour réussir à faire ce que je veux .

    Voici donc mes tables :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
    CREATE TABLE `type_building` (
      `type` int(11) NOT NULL,
      PRIMARY KEY  (`type`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
     
    -- 
    -- Contenu de la table `type_building`
    -- 
     
    INSERT INTO `type_building` (`type`) VALUES 
    (0),
    (1),
    (2),
    (3),
    (4),
    (5),
    (6);
     
    CREATE TABLE `test_building` (
      `id` int(11) NOT NULL auto_increment,
      `type` int(11) NOT NULL,
      `level` int(11) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
     
     
    INSERT INTO `test_building` (`id`, `type`, `level`) VALUES 
    (1, 0, 2),
    (2, 0, 3),
    (3, 1, 4),
    (4, 2, 5),
    (5, 1, 3),
    (6, 0, 2);
     
    CREATE TABLE `condition_building` (
      `id` int(11) NOT NULL auto_increment,
      `type_cible` int(11) NOT NULL,
      `type_requis` int(11) NOT NULL,
      `level_requis` int(11) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
     
     
    INSERT INTO `condition_building` (`id`, `type_cible`, `type_requis`, `level_requis`) VALUES 
    (1, 2, 0, 2),
    (2, 2, 1, 6),
    (3, 4, 3, 1);
    (4, 3, 0, 1);
    Le but est désormais une requête qui renvoie la liste des types de bâtiments que l'on peut construire.

    Dans l'exemple présent, je résume les données :

    Le bâtiment de type 2 peut être construit si on a un bâtiment de type 2 et de niveau >=2 ET un bâtiment de type 1 et de niveau>=6 (ce n'est pas le cas)
    La bâtiment de type 4 peut être construit si on a un bâtiment de type 3 et de niveau >=1 (ce n'est pas le cas)
    La bâtiment de type 3 peut être construit si on a un bâtiment de type 0 et de niveau >=1 (c'est le cas)

    Lorsqu'il n'y a pas de conditions le concernant, un type de bâtiment est constructible.

    Donc, la requête doit renvoyer comme types disponibles :

    0, 1, 3, 5, 6

    Voici ma requête à l'heure actuelle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT *
    FROM type_building as t
    WHERE NOT EXISTS
    (SELECT * FROM condition_building as c, test_building as b 
    		WHERE  c.type_cible = t.type AND (b.type=c.type_requis and b.level<c.level_requis))
    Le problème, c'est que j'ai comme résultat :
    0, 1, 3, 4, 5, 6

    Le 4 est en trop, car on n'a aucun bâtiment de type 3. Il faut donc que je modifie la requête, pour qu'une condition soit sélectionnée si le niveau n'est pas bon OU SI le bâtiment n'existe pas.

    Ca devrait ressembler à quelque chose comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    SELECT *
    FROM type_building as t
    WHERE NOT EXISTS
    (SELECT * FROM condition_building as c, test_building as b 
    		WHERE  c.type_cible = t.type AND ((b.type=c.type_requis and b.level<c.level_requis) OR (NOT 
     
    EXISTS(??))))
    La question est : que mettre dans les ?? . Ya ptet moyen de faire plus simple non ?

    Merci d'avance . En tout cas, les choses sont beaucoup plus claires pour moi maintenant, merci !!

    @++

    Piwaï

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MCD] Est ce que ce MCD application de gestion de paie est correct ?
    Par hafcher dans le forum Schéma
    Réponses: 1
    Dernier message: 11/07/2008, 19h16
  2. Est ce que ce code est correct ?
    Par foot.c dans le forum Débuter
    Réponses: 6
    Dernier message: 12/05/2008, 01h49
  3. [log4j]Est-ce que je m'y prend correctement ?
    Par verbose dans le forum Logging
    Réponses: 5
    Dernier message: 28/02/2008, 17h04
  4. est-ce que wx-config donne qqch de correct ?
    Par [Hugo] dans le forum Applications et environnements graphiques
    Réponses: 6
    Dernier message: 30/10/2007, 13h46
  5. [GRASP] Est-ce que j'utilise correctement les design pattern?
    Par Tourix dans le forum Design Patterns
    Réponses: 7
    Dernier message: 21/06/2006, 18h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo