Infos joueurs & comptes
Salut, j'ai essayé de faire quelques requêtes aujourd'hui pour réviser un peu de SQL.
Rien de sorcier mais ça pourrait être utile à certains donc je me permets de les poster Oui.

Explications générales
LIMIT
LIMIT n nous permet de limiter le nombre de résultat à n au maximum pour notre requête.

ORDER BY
ORDER BY nom_de_colonne nous permet de trier les résultats de notre requête selon la colonne donnée, en ordre croissant.
Pour trier en ordre décroissant, on utilisera ORDER BY nom_de_colonne DESC.

INNER JOIN
L'utilisation de jointures (ou en anglais "join") en SQL permet de mettre en relation différentes tables. L'Inner join est très utile et est de loin le plus simple à utiliser, comme le montre l'exemple ci-dessous.
SELECT * 
 FROM tableA
  INNER JOIN tableB
   ON tableA.key = tableB.key;
Ce bout de code nous permet de récupérer toutes les lignes des tables tableA et tableB ayant la même valeur pour la colonne key.

CONCAT
Comme son nom l'indique, la fonction CONCAT nous permet de concaténer deux variables entre elles. Le code ci-dessous nous renverra donc 'Hello World'.
CONCAT('Hello ', 'World');

COUNT
La fonction COUNT nous permet de compter le nombre d'occurence d'une certaine valeur dans nos tables. Elle est presque tout le temps utilisé avec un GROUP BY qui nous permet de préciser sur quelle colonne nous allons chercher les valeurs récurrentes.
Imaginons une table users avec une colonne id et name, remplie avec les données suivantes :
INSERT INTO users (name) VALUES
('david'),
('bob'),
('jean'),
('kevin'),
('bob'),
('jean'),
La requête ci-dessous nous renverra 2 pour bob, 2 pour jean, 1 pour david et 1 pour kevin.
SELECT name, COUNT(*)
 FROM users
  GROUP BY name;
Vous pouvez mettre n'importe quel nom de colonne dans les parenthèses du COUNT ou comme moi un * si vous ne voulez pas vous prendre la tête, le résultat sera toujours le même.

SUM
La fonction SUM fonctionne de la même manière que COUNT. Mais au lieu de compter le nombre d'occurences d'une valeur, elle va faire la somme de chaque valeur de la colonne spécifiée. Reprenons la table précédentes comme exemple avec une nouvelle colonne money.
INSERT INTO users (name, money) VALUES
('david', 10),
('bob', 10),
('jean', 15),
('kevin', 20),
('bob', 5),
('jean', 10),
Le code ci-dessous renverra alors 10 pour david, 15 pour bob, 25 pour jean et 20 pour kevin.
SELECT name, SUM(money)
 FROM users
  GROUP BY name;

Les requêtes
Inventaire et équipement d'un personnage
Cette requête liste tout l'inventaire et l'équipement d'un personnage donné.
SET @perso = 'nom_de_personnage';
SELECT item_template.name AS item, COUNT(*) + item_instance.count - 1 AS count
  FROM characters.character_inventory
    INNER JOIN characters.item_instance
      ON characters.character_inventory.item = characters.item_instance.guid
        INNER JOIN world.item_template
	  ON world.item_template.entry = characters.item_instance.itemEntry
	    INNER JOIN characters.characters
	      ON characters.characters.guid = characters.character_inventory.guid
	        WHERE characters.characters.name LIKE @perso
        	  GROUP BY item_template.name
	            ORDER BY count DESC, item_template.name;
Cette requête n'est pas aussi compliquée qu'elle n'en à l'air, elle est juste très chiante à écrire. Du coup, je ne suis pas sur de réussir à l'expliquer de manière très claire mais je me lance tout de même.

On veut donc récupérer le nom de chaque item que possède un personnage ainsi que sa quantité. On commence dans characters.character_inventory, qui stocke le contenu complet des sacs de chaque joueur. Malheureusement cette table stocke seulement le GUID de l'objet (un identifiant unique pour chaque objet dans le jeu). Nous aimerions donc récupérer le nom de l'objet (qui est stocké dans world.item_template). On commence alors par faire une jointure sur characters.item_instance afin de récupérer l'entry de chaque objet. Puis on fait une nouvelle jointure sur world.item_template pour récupérer le nom de l'objet associé à l'entry.

La dernière jointure sur characters.characters nous permet de récupérer le GUID du personnage souhaité à partir de son nom. Cette étape est nécessaire car la table characters.character_inventory associe chaque objet à un personnage grâce au GUID de son propriétaire et non son nom.

Enfin, le COUNT(*) + item_instance.count - 1 count sur la première ligne permet de n'avoir qu'une seule ligne par objet, en gérant le cas où un objet ne peut pas être stacké dans les sacs (les armes et armures par exemple) et appraraîtrait ainsi plusieurs fois dans le résultat.

Personnages d'un compte
Cette requête liste tous les personnages d'un compte donné avec le niveau et le temps de jeu de chacun des personnages.
SET @compte = 'nom_de_compte';
SELECT username, name, level, CONCAT(totaltime/3600, 'h') AS played
  FROM characters.characters
    INNER JOIN auth.account ON auth.account.id = characters.characters.account
      WHERE username LIKE @compte;
On récupère ici les noms, niveaux et temps de jeu de tous les personnages, stockés dans characters.characters d'un compte donné, stocké dans auth.account. L'unité de temps de jeu est la seconde, donc on divise par 60*60 pour avoir la somme en heure.

Argent et temps de jeu d'un compte
Cette requête liste tous les comptes de la base de données avec le gold et le temps de jeu total de tous les personnages du compte.
SELECT username, SUM(money)/10000 AS gold, CONCAT(SUM(totaltime)/3600, 'h') AS played
  FROM auth.account
    INNER JOIN characters.characters ON auth.account.id = characters.characters.account
      GROUP BY characters.characters.account
        ORDER BY gold DESC, played DESC;
On récupère le nom du compte à partir de la table auth.account, puis on fait le lien avec un INNER JOIN sur la table characters.characters pour récupérer tous les personnages de chaque compte. On récupère les gold (money) et le temps de jeu (totaltime) total avec SUM. L'unité d'argent est la pièce de cuivre, donc on divise par 10000 pour avoir la somme en pièce d'or.

Top 10 haut-faits
Cette requête liste les 10 personnages du serveur ayant le plus de haut-faits.
SELECT characters.name, COUNT(character_achievement.guid) AS achievements
  FROM characters.character_achievement
    INNER JOIN characters.characters
      ON characters.characters.guid = characters.character_achievement.guid
        GROUP BY characters.character_achievement.guid
	  ORDER BY achievements DESC
	    LIMIT 10;
On récupère le nom du personnage dans characters.characters et on fait le lien avec characters.characters_achievement qui énumère chaque haut-fait de chaque personnage. Le COUNT nous permet donc de récupérer le total de haut-faits effectués.

Top 10 PvP
Cette requête liste les 10 personnages du serveur ayant le plus de kills.
SELECT @ranking := @ranking + 1 AS rank, name, totalkills
  FROM characters.characters, (SELECT @ranking := 0) r
   ORDER BY totalkills DESC
     LIMIT 10;
On récupère le nom du personnage et son nom de kills à partir de la table characters.characters, et on déclare une variable ranking qu'on initialise à 0 et qu'on incrémente à chaque ligne récupérée pour associer le personnage à son rang dans le classement (de 1 à 10).

Teams 2v2
Cette requête liste toutes les teams d'arène 2v2 du serveur avec leurs membres par mmr.
SELECT arena_team.name AS team, characters.name AS members, rating
  FROM characters.arena_team
    INNER JOIN characters.arena_team_member
      ON characters.arena_team.arenaTeamId = characters.arena_team_member.arenaTeamId
        INNER JOIN characters.characters
      	  ON characters.characters.guid = characters.arena_team_member.guid
       	    WHERE type = 2
      	      ORDER BY rating DESC;
On commence par récupérer le nom de la team dans characters.arena_team. On cherche ensuite à connaître les membres de chaque team en faisant une jointure sur characters.arena_team_member. Mais seuls les GUID des personnages sont stockés dans cette table, donc on fait une seconde jointure sur characters.characters pour récupérer le nom du personnage correspondant au GUID.

Liste des guildes
Cette requête liste toutes les guildes du serveur avec le nom du guildmaster et le nombre de membres.
SELECT guild.name, characters.name AS leader, COUNT(guild_member.guid) AS members
  FROM characters.guild
    INNER JOIN characters.characters
      ON characters.guild.leaderguid = characters.characters.guid
        INNER JOIN characters.guild_member
          ON characters.guild.guildid = characters.guild_member.guildid
       	     GROUP BY guild_member.guildid
	       ORDER BY members DESC;
On commence par récupérer les guildes avec leur nom dans la table characters.guild. Un INNER JOIN entre characters.guild et characters.characters nous permet de récupérer le nom du chef de guilde grâce à son GUID. Un INNER JOIN supplémentaire sur characters.guild_member associé à un COUNT nous permet de récupérer le nombre de membres de la guilde.
Merci pour ces requêtes qui peuvent se montrer très utile ! Smile
Merci pour ton partage !
Je déplace cependant dans Fichiers & Scripts, puisque tu ne proposes pas d'explications Smile
C'était surtout pour que tout le monde puisse le voir, mais bon pas de problème Pouce haut
(06-04-2014 22:18)Warryur a écrit :  Merci pour ton partage !
Je déplace cependant dans Fichiers & Scripts, puisque tu ne proposes pas d'explications Smile

En effet, c'est dommage que des explications ne soient pas livrées en plus étant donné que tes requêtes sont, tout de même, assez complexes en écriture Wink

Merci, au passage !
Bon ok je fais une explication pour ce soir si j'ai le courage ou sinon pour demain Angel
Explications ajoutées. J'ai beau m'être relu, certaines explications sont assez difficiles pour moi à formuler à l'écrit. Donc les modos si vous voyez des choses à modifier ou à clarifier vous gênez pas vous avez carte blanche Troll
Niquel, je vaiq pouvoir réviser a mon tour, super rappel de ta part Smile
Serait-il possible de redéplacer le topic dans tutoriels ?
Je ne vois aucun tutoriel dans ton partage.
Tout est déjà fait, c'est donc un release, et c'est pour ça que ça a été move.
PEut-être serait-il plus judicieux de séparer les explications des scripts ? C'est toi qui voit Wink
Bah du coup vous devriez déplacer tous mes posts en fichiers & scripts vu que je fournis directement le code à chaque fois Angel

Retourner en haut WoW-Emu