Requête MySql à la mord-moi-le-noeud

Répondre
Partager Rechercher
Non, il ne s'agit pas d'une requête pour un éventuel site pornographique mais bel et bien d'une requête que je n'arrive pas à monter

Voilà le topo...

J'achete et revend des quantités différentes d'objets différents à des prix différents. Les gens achètent mes différents objets à des quantité différentes et à des prix différents

En gros, ma table ressemble à ça
id - objet - quantite - prix - achat/vente
1 - lait - 10 - 10 - 1
2 - lait - 20 - 8 - 1
3 - thé - 14 - 20 - 1
4 - lait - 5 - 12 - 0
5 - lait - 7 - 13 - 0
6 - lait - 2 - 20 - 0
7 - thé - 5 - 16 - 0

(Si 1 alors c une vente sinon c un achat... ou le contraire, ça marche aussi mais à l'envers de toute façon)

Je voudrais une requete qui me classe tout ça par bénéfice.

En gros:
* si je vend id1 à id4:
J'achete 5 lait (puisqu'il n'a pas besoin de plus) à 10€ et je les revend à 12€ soit un bénéf de 10€
* si je vend id1 à id5:
J'achete 10 lait (puisqu'il ne vend pas plus) à 10€ et je les revend à 13€ soit un bénéf de 30€
* si je vend id3 à id7:
J'achete 10 5 (puisqu'il n'a pas besoin de plus) à 20€ et je les revend à 16€ soit un bénéf négatif... pof, j'ignore cette ligne

donc sur mon rapport, il y aura :
1 - id1 - id5 - 30€
2 - id1 - id4 - 10€

Alors ça, c'est assez simple en traitant avec du php. Le problème que je rencontre c'est le nombre d'accès assez énorme à la base de données à chaque fois que je veux afficher un rapport. En effet, je me limite pas à 2 objets mais à près de 5000 et j'ai quasiment dix fois plus d'acheteurs/vendeurs

La solution d'une requete unique me semblait la moins gourmande en ressource mais je suis incapable de monter une telle requete.

Je suis bien sur preneur de toute autre solution
En admettant que j'ai bien compris ce que tu demandes, je ne pense pas que ça sera plus rapide avec une requête unique.
En effet, ce que tu demandes ressemble à un produit cartésien.
Limiter aux offres concernant un seul produit serait peut-être plus simple.
Quitte à faire exécuter, par le code php, la requête pour chaque produit.

Tu es face à une problématique courante dans le client/serveur : quelle partie doit être traitée par l'appli, et quelle partie doit être traitée côté base de données ?

Néanmoins, voici une ébauche de requête (que je n'ai pu tester, étant au boulot *ahem*). Quand je serais de retour chez moi, je pourrais tester plus efficacement, car j'ai déjà une base contenant une table ressemblant énormément à la tienne.
Je vais d'ailleurs reprendre, dans mon exemple, les noms de champs de ma table à moi.

Soit la table traMarketOrders, contenant les champs orderID, typeID, volRemaining, price, bid.
orderID est l'identifiant de l'ordre de vente/achat, typeID est l'identifiant de l'objet vendu/recherché, volRemaining le nombre vendu/recherché, price le prix et bid un booléen indiquant s'il s'agit d'une vente (0) ou d'un achat (1).

Voici la requête que j'ai fait rapidement (c'est un produit cartésien, donc l'exécution risque d'être très très longue).

Code:
select 
    o1.orderID, 
    o2.orderID, 
    (o2.price - o1.price) * IF(o1.volRemaining > o2.volRemaining, o2.volRemaining, o1.volRemaining) AS iskGained
from traMarketOrders o1, traMarketOrders o2
where o1.bid = 0
and o2.bid = 1
Comme je n'ai pas pu la tester, cette requête est fournie telle qu'elle, sans aucune garantie.
plop,

au depart, je pensais que tu voulais faire des statistiques sur tes données mais pas du tout... en fait tu veux ajouter de l"intelligence" a ton système pour que ca te sorte un résumé des transactions les plus "efficaces" j'ai bon?

bon perso si j'avais a faire ce genre de calculs...

deja je le ferai pas "dans" la bd donc pas avec une requête unique...

je ferais un programme du style (en pseudo code, j'ai pas envie de me prendre la tete)

liste des objets en bd => A

pour chaque objet de A
{
listes des transactions en bd de cet objet => B
appliquer ton intelligence a B
garder le résultat dans un tableau C
}

afficher C qui est le résultat

comme ca te fait des requetes pas trop lourde dans ta bd si tu as bien indexé ta table (ici sur le champ objet)
et c'est pas la bd qui mouline les calculs

ca devrait etre plus efficace comme ca

amicalement
Wardead

edit : bon ben burned par julian...
a part que moi je degagerais aussi le calcul de benefice de la bd... mais bon...
et tu as raison la problematique est assez classique des que tu bricole un nombre de lignes en bd important...
Merci à tous les deux pour avoir pris le temps de me comprendre et de me répondre

Julian, il y a des notations que je ne connaissais pas pour une requête comme pour le "from traMarketOrders o1, traMarketOrders o2". De suite, ça ouvre énormément de possibilités qui m'étaient interdites jusqu'à présent.

Wardead, la solution d'un tableau est intéressante et je vais plutôt utiliser une classe en php.

Je pense maintenant être capable, en mixant vos deux solutions, de pouvoir sortir le tableau dont j'ai besoin.

Merci encore
Pour l'affichage c'est en effet ce qu'il se fera de plus performant.

Il faut néanmoins générer les enregistrements de cette table à chaque modification de la table traMarketOrders (pour reprendre l'exemple de Julian).

C'est une solution intéressante que je vais tester. En mixant tout ça je devrai pouvoir faire un truc pas trop mal et assez réactif
replop,

c est clair que ce qu'on a avancé avec julian, c est un "code" qui permet d'analyser les données pour en tirer une analyse qui n'est finalement valable qu'au moment ou est lancé le process => c est un "état" en quelque sorte.

et donc a chaque fois que tu veux un "état" a jour, il faut relancer tout le calcul qui est assez long...

en fait (merci [un pseudo] )on en vient rapidement a la question "est ce que ca serait pas con que je foute ca dans une table dédiée, en faisant en sorte que les calculs se remettent a jour quand j'ajoute ou je retire une transaction?"

bon en gros y a pas a tortiller, les calculs faut bien les faire a un moment et effectivement a mon sens si on veux avoir une vision a jour du truc accessible facilement, le mieux c est de faire le calcul se rapportant a l'objet concerné a chaque nouvelle donnée...
c est un problème qui peux arriver très facilement si on a besoin que plusieurs personnes en même temps accèdent aux données calculées... lancer en même temps 2 requêtes de calcul sur toute la base... bonjour le temps de réponse.


j'attire ton attention sur un point qui m'étonne un peu, y a pas de notion de temps dans ton truc? genre une date d'entree de transaction et/ou une date quand il faut que ca soit fait?

parce que plus tu voudra rajouter de critères pour le calcul plus la solution de faire les calculs a l'entrée des données se justifie.
et accessoirement, ce genre de truc vaut mieux le prévoir des le départ, sinon (tu peux me croire sur parole) c est l'enfer

amicalement

Wardead
Vu que le monsieur a parfois posté sur le forum Eve Online, je pense que sa table ressemble à quelque chose dans le genre.

Code:
CREATE TABLE `traMarketOrders` (
  `orderID` int(10) unsigned NOT NULL default '0',
  -- identifiant de l'ordre
  `price` double unsigned NOT NULL default '0',
  -- prix unitaire
  `volRemaining` int(10) unsigned NOT NULL default '0',
  -- nombre d'unités restant recherché/à vendre
  `volEntered` int(10) unsigned NOT NULL default '0',
  -- nombre d'unités original
  `minVolume` int(10) unsigned NOT NULL default '0',
  -- nombre d'unités minimum par transaction
  `range` smallint(6) NOT NULL default '0',
  -- portée de l'ordre (station, système, x jumps, région)
  `bid` tinyint(1) unsigned NOT NULL default '0',
  -- 0 si ordre de vente, 1 si ordre d'achat
  `issued` date NOT NULL default '0000-00-00',
  -- date de parution de l'ordre
  `duration` mediumint(4) unsigned NOT NULL default '0',
  -- durée de validité de l'ordre
  `typeID` int(10) unsigned NOT NULL default '0',
  -- identifiant de l'objet vendu/recherché
  `stationID` int(10) unsigned NOT NULL default '0',
  -- identifiant de la station où l'ordre a été passé
  `regionID` int(10) unsigned NOT NULL default '0',
  -- identifant de la région
  `solarSystemID` int(10) unsigned NOT NULL default '0',
  -- identifiant du système
  `chgWho` varchar(20) NOT NULL default '',
  -- login utilisé pour mettre à jour les ordres dans l'appli
  `chgDateTime` datetime NOT NULL default '0000-00-00 00:00:00',
  -- date d'ajout ou de mise à jour
  `isDeleted` tinyint(1) unsigned NOT NULL default '0',
  -- deprecated
  PRIMARY KEY  (`orderID`),
  KEY `typeID_IDX` (`typeID`),
  KEY `regionID_IDX` (`regionID`),
  KEY `traMarketOrders_IDX1` (`typeID`,`bid`),
  KEY `chgWho` (`chgWho`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Les trois derniers champs on été rajoutés par moi, de même que les index.

Il faut savoir que les développeurs de ce jeu propose un "data dump" de la plupart des tables statiques du jeu.
De plus, le commerce d'Eve utilise un système d'ordres.
On peut passer un ordre d'achat de tant d'unités de machin, pour tel prix unitaire, avec une validité de l'ordre pour tant de jours.
L'interface du marché permet de faire une extraction de tous les ordres d'une région concernant un objet.
Nous voila donc face à une table dynamique. ^^

Donc, si je ne me suis pas trompé quant au hobby de samche, il a effectivement beaucoup plus d'infos.
En effet Julian c'est exactement ça... d'ailleurs je te contacte par mp pour plus d'infos

je ne m'étais pas plus étendu sur les détails car mon soucis principal était ce fameux produit cartésien que tu m'as résolu avec ta requête.

Pour le reste, j'avoue que je me tâte entre stocker les données dans une table ou bien générer une page html... ou bien les deux. Tout dépendra de quelle solution sera la plus performante autant en terme de performance que de gain de place.
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés