[MySQL] Cherche 3eme dan Optimisation: requette avec SubQuery correlée

Cherche 3eme dan Optimisation: requette avec SubQuery correlée [MySQL] - SQL/NoSQL - Programmation

Marsh Posté le 31-08-2005 à 15:36:37    

bonjour :)
 
voila j'ai un problème que je retourne dans tous les sens depuis quelques temps déja et je ne parviens pas a trouver de solution optimale (entendre rapide)
 
j'ai 2 table, une avec bcp d'enregistrements d'appels téléphonique(unixTime d'appel, numéro appelé, oppérateur utilisé)
l'autre avec une grille de prix(unixTime de validité du prix, code pays, opperateur,prix)
 
ce que je cherche c'est a récupérer pour chaque appel le prix qu'il a couté
, en fonction de quand, par quel oppérateur et vers quelle destination.
 
assez de blabla, voici ou j'en suis arrivé:  

Citation :

SELECT CDR.UnixTime, CDR.DestNum, CDR.ReselerID, (SELECT RateTable.Price
          FROM RateTable
          WHERE RateTable.AreaCode = LEFT(CDR.DestNum,LENGTH(RateTable.AreaCode))
                AND RateTable.ReselerID = CDR.ReselerID
                AND RateTable.EffectUT < CDR.UnixTime
          ORDER BY RateTable.EffectDate DESC, RateTable.AreaCode DESC
          LIMIT 0,1) as 'Price'
FROM (SELECT DestNum, UnixTime, ReselerID FROM IPNX_CDR LIMIT 0,100) CDR
ORDER BY CDR.DestNum;


 
le problème est que c'est relativement lent car pour chaque ligne de la table CDR, il génère une sous requette.
 
j'ai essayé de passer par un JOIN, mais il n'accepte pas la référence a la colone a l'exterieur de la requette (a l'inverse du cas précédant)

Citation :

SELECT IPNX_CDR.UnixTime, IPNX_CDR.DestNum, IPNX_CDR.ReselerID, RT1.AreaCode, RT1.Price
FROM IPNX_CDR
        ,(SELECT AreaCode, ReselerID, EffectUT
          FROM RateTable
          WHERE AreaCode = LEFT(IPNX_CDR.DestNum,LENGTH(AreaCode))
                AND ReselerID = IPNX_CDR.ReselerID
                AND EffectUT < IPNX_CDR.UnixTime
          ORDER BY EffectDate DESC, AreaCode DESC
          LIMIT 0,1) as RT1
ORDER BY IPNX_CDR.DestNum;
LIMIT 0,100;


 
donc j'ai un cas qui fonctionne mais qui est lent (si je rajoute 1 champ ça m'oblige a rajouter une sous requette)
et l'autre qui ne fonctionne pas.
 
j'espère profiter de vos conseils :)
merci.
 
voir mon 3eme msg pour les tables.


Message édité par Kytrix le 02-09-2005 à 10:18:41
Reply

Marsh Posté le 31-08-2005 à 15:36:37   

Reply

Marsh Posté le 31-08-2005 à 18:27:41    

j'ai peut etre pas bien compris la structure de ta bdd
mais pour moi un appel aun seul prix et un truc du style devrait marcher:
 

Code :
  1. SELECT appels.UnixTime, appels.DestNum, appels.ReselerID,grilleprix.prix
  2. from appels inner join prix on (AreaCode = LEFT(appels.DestNum,LENGTH(AreaCode))) and (ReselerID = appels.ReselerID ) and (AND EffectUT < appels.UnixTime)


Message édité par betsamee le 31-08-2005 à 18:28:23
Reply

Marsh Posté le 31-08-2005 à 18:50:38    

betsamee> En fait pour un numéro appelé (DestNum) il y a un seul prix effectivement, mais je dois déterminer quel est ce prix (d'ou la recherche du plus grand AreaCode.. contenu dans le numéro).  
si j'execute la recherche que tu m'as donnée il va me sortir autant de ligne que de AreaCode qui correspondent au numéro (mais moi je veux le plus grand). donc au final une ligne par ligne de ma table CDR.
 
c'est un peu plus clair ?
 

Reply

Marsh Posté le 31-08-2005 à 19:00:31    

en simplifiant mes tables :
 
table CDR:

Code :
  1. DestNum   |Operateur|
  2. 256698557 |        1|
  3. 3315896589|        3|


Table Prix:

Code :
  1. AreaCode | Operateur| Prix
  2. 25669    |         1|   1.2
  3. 25670    |         1|   0.7
  4. 256      |         1|   0.5
  5. 3315     |         1|   0.1
  6. 33       |         1|   0.1
  7. 256698   |         2|   1.1
  8. 25670    |         2|   0.2
  9. 256      |         2|   0.3
  10. 331580   |         3|   0.8
  11. 33158    |         3|   0.85
  12. 33       |         3|   0.8


j'ai besoin de sortir (+rapidement qu'avec la méthode citée plus haut):
 

Code :
  1. DestNum   | AreaCode | Operateur | Prix
  2. 256698557 |25669     |          1|1.2
  3. 3315896589|33158     |          3|0.85


j'ai suprimer certaines colones mais le principe est là
 
:)


Message édité par Kytrix le 31-08-2005 à 19:02:46
Reply

Marsh Posté le 31-08-2005 à 22:01:44    

ouaip en effet la c'est pas simple

Reply

Marsh Posté le 01-09-2005 à 09:14:31    

up du matin :)
 
si vous voulez + d'infos n'hésitez pas :)

Reply

Marsh Posté le 02-09-2005 à 10:09:31    

bon réponsez au moins au questionnaire :)
marci.

Reply

Marsh Posté le 02-09-2005 à 11:41:26    

ce n'est envisageable de modifier la structure de tes tables?

Reply

Marsh Posté le 02-09-2005 à 11:48:55    

oui oui c'est envisageable :)
seule contrainte (enfin de mon point de vue) garder 2 table distinctes pour que ça soit plus facile a gérer (et plus propre).
:)

Reply

Marsh Posté le 02-09-2005 à 11:52:39    

et bien je rajouterai une colonne a la table CDR avec l'areacode correspondant que tu calcules au moment de l'insertion d'un appel ou bien au moment de tes stats pour les valeurs non remplies...
vouloir faire de la super requete pourquoi pas, mais si cette solution est envisageable niveau stockage et programmes qui tournent autours...

Reply

Marsh Posté le 02-09-2005 à 11:52:39   

Reply

Marsh Posté le 02-09-2005 à 11:57:20    

casimimir : mon problème c'est que j'ai quelques millions de lignes a réinssérer.. donc recalculer .. et ça risque de me prendre des jours .. de plus si je décide de re-changer des prix, je devrai tout refaire :S
 
c'est vrai que calculer au niveau de l'insertion c'est suffisament rapide, il suffit de ne pas prendre trop de retard .. et c'est ce que je fais pour les nouvelles données.. mais pour les anciennes c'est pas facile d'etre rapide :/
 
merci :)

Reply

Marsh Posté le 02-09-2005 à 12:13:31    

le prix se trouve au niveau de la table Prix donc tu pourras les changer sans probleme... l'idée c'est de mettre une foreign key dans ta table CDR qui pointe vers ta table Prix.
ca peut prendre du temps mais pour les quelques jours j'en doute meme si il y a qques millions de lignes, puis rien ne t'empeche d'étaler ca sur plusieurs jours.
'fin perso c'est ce que je ferai

Reply

Marsh Posté le 02-09-2005 à 12:18:41    

foreign key !! je connaissait pas :D
je vais me reseigner sur le site de mysql :)
merci

Reply

Marsh Posté le 02-09-2005 à 13:07:49    

si tes tables sont en MyISAM et non en InnoDB oublies le foreign key

Reply

Marsh Posté le 02-09-2005 à 13:16:38    

merde :D  
c'est du MyISAM

Reply

Marsh Posté le 05-09-2005 à 08:33:47    

j'ai dis foreign key pour dire quelles données on allait retrouver dans ce champ, on peut encore se passer raisonnablement de l'intégrité meme si c'est toujours un plus.
 
mysql supporte quand meme les inner join ou alors il ne cessera jamais de me décevoir? ^^

Reply

Marsh Posté le 05-09-2005 à 08:35:50    

oui quand meme , toutes les jointures sauf le full outer join :D

Reply

Marsh Posté le 06-09-2005 à 22:59:51    

Ce qui est bizarre, c'est que tu n'as pas le coût de l'appel dans ta table RateTable. A moins que tu ne l'aies, mais que tu cherches le coût à la seconde ...
 
Je bosse beaucoup sur des systèmes de Rating, et généralement, un appel facturé contient toutes les infos de coût ... :)

Reply

Marsh Posté le 07-09-2005 à 02:19:24    

j'ai le coup a la minute dans RateTable ... et je cherche a m'en servir pour trouver le coup d'appel (en fonction de la durée et du numéro appelé) .. dans CDR
 
là je fait tourner une requette du meme style que celle du dessus ...
et ça met 15s pour 100 enregistrements :'(
le pc va tourner 8 jours pour faire les 4 000 000 que je dois traiter ... super :)
 

Reply

Marsh Posté le 07-09-2005 à 07:37:27    

Je m'étais trompé de nom de table, je voulais parler de la table CDR.
 
Donc dans CDR, tu as les appels non facturés ? :)

Reply

Marsh Posté le 07-09-2005 à 09:38:20    

en fait j'ai la facturation du matériel qui me fournit les log d'apels,
mais c'est notre facturation sur les cartes prépayées (c'est un switch d'appel pour carte prépayées).. mais lui ne sait pas faire la facture oppérateur(il n'a mme pas les rates opérateurs soit dit en passant).. donc il faut que je retraite les données a part .. ce que je suis en train de faire.
voila :)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed