Double tri limité sur chaque critère en MySql

Double tri limité sur chaque critère en MySql - SQL/NoSQL - Programmation

Marsh Posté le 20-02-2012 à 01:34:49    

Bonjour,
Pour une extension WordPress (StatPress-Visitors) que j'entretiens, j'ai besoin de faire un double tri avec une limitation de la recherche sur chaque critère de tri.
En plus clair, pour des stats, je veux afficher les 20 dernières visites des 50 dernières IP, ce qui correspond au log des visites (appelé SPY).
Je tente en vain de trouver une requête qui ne renvoit que ces résultats là.
 
La requête la plus rapide que j'ai trouvé utilise l'index primaire de la table de donnée (id) et est la suivante - elle fait une auto jointure de la table sur elle même - mais elle retourne toutes les visites des 50 dernières IP, et non pas uniquement les 20 dernières visites des 50 dernières IP - cela ne pose pas trop de problèmes car les IP sont rarement les mêmes d'un jour à l'autre sur mon site - :

Code :
  1. SELECT *
  2.     FROM $table_name as T1
  3.     JOIN
  4.      (SELECT max(id) as MaxId, ip
  5.       FROM $table_name
  6.       WHERE spider=''
  7.       GROUP BY ip
  8.       ORDER BY MaxId DESC LIMIT $LimitValue, $LIMIT
  9.      ) as T2
  10.     ON T1.ip = T2.ip
  11.     ORDER BY MaxId DESC, id DESC


 
J'ai tenté de numéroter les lignes en partant de 0 pour chaque IP, mais cela ne fonctionne pas, cela incrémente toutes les lignes indépendamment des IP (s'il y a 1000 lignes, alors cela numérote jusqu'à 1000) :

Code :
  1. SELECT *, @num:=@num+1 as numero
  2.                     FROM $table_name as T1
  3.                     JOIN
  4.                         (SELECT max(id) as MaxId, ip, @num:=0 as numero
  5.                             FROM $table_name
  6.                             WHERE spider=''
  7.                             GROUP BY ip
  8.                             ORDER BY MaxId DESC LIMIT $LimitValue, $LIMIT
  9.                         ) as T2
  10.                     ON T1.ip = T2.ip
  11.                     HAVING numero < 20
  12.                     ORDER BY MaxId DESC, id DESC


 
Le seul problème que j'ai avec la première requête n'est pas son temps d'excécution, mais son traitement en PHP. En effet, si la requête renvoit pour une table de 150 000 lignes, 1000 lignes en 1,6 sec. Leur traitement en PHP - qui n'est pas un langage compilé - prend sur mon site en local 30 secondes, ce qui est catastrophique.
 
Bon, malgré tout cette requête est plus rapide que celle du StatPress Original - qui elle fait un premier tri pour sélectionner les 50 dernières IP et fait 50 requêtes (une par IP) pour renvoyer les 20 dernières visites sur la table de donnée entière.
 
J'ai aussi fait une variante qui utilise une table temporaire contenant tous les résultats de la première requête, puis j'ai interrogé cette table autant de fois qu'il y a d'IP - comme le fait le StatPress Original -, cela n'accélère pas le traitement final par rapport à la première requête (mais l'accélère par rapport au StatPress original et ses dérivés), je ne vais pas plus vite, ni plus lentement d'ailleurs.
Est-il possible de faire en MySql un double tri selon deux critères différents en limitant séparemment le nombre de lignes renvoyées pour chaque critère ?
 
Je sèche complétement, toutes mes tentatives ont échouées.  
 
 - mais peut-on faire encore mieux en MySql ou est-ce comme il me semble impossible ?
 
Merci de vos lumières.


Message édité par luciole135 le 20-02-2012 à 01:35:39

---------------
Mon site perso quand on veut arrêter de fumer sans manque physique ni prise de poids  : http://additifstabac.webuda.com/
Reply

Marsh Posté le 20-02-2012 à 01:34:49   

Reply

Marsh Posté le 20-02-2012 à 09:52:58    

Heu... un truc du genre :

Code :
  1. SELECT
  2.    *
  3. FROM
  4.    TABLE T1
  5. WHERE T1.T2_ID IN (
  6.    SELECT
  7.        T2.T2_ID
  8.    FROM
  9.        T2
  10.    ORDER BY
  11.       T2.ORDER_COL DESC
  12.     LIMIT
  13.        20
  14.    )
  15. ORDER BY
  16.    T1.ORDER_COL DESC
  17. LIMIT
  18.    50
  19. ;


 
Sans doute pas 100% syntaxiquement exact, mais l'idée est là je pense... :??:


---------------
| AMD Ryzen 7 7700X 8C/16T @ 4.5-5.4GHz - 64GB DDR5-6000 30-40-40 1T - AMD Radeon RX 7900 XTX 24GB @ 2680MHz/20Gbps |
Reply

Marsh Posté le 20-02-2012 à 10:57:57    

Cela répond que ma version de MySql (la dernière ) ne permet pas de faire un LIMIT dans un IN !
 
Merci encore !

Reply

Marsh Posté le 20-02-2012 à 11:06:16    

Avec un truc du genre :

Code :
  1. SET @rownum :=0;
  2. SELECT @rownum := @rownum + 1 AS 'ID', EmployeeName FROM Employees


 
Bon j'ai vu ça sur Google... :o
Après tu fait un where rownum between 1 and 20.
 
C'est un peu laid mais bon... :'(


---------------
| AMD Ryzen 7 7700X 8C/16T @ 4.5-5.4GHz - 64GB DDR5-6000 30-40-40 1T - AMD Radeon RX 7900 XTX 24GB @ 2680MHz/20Gbps |
Reply

Marsh Posté le 20-02-2012 à 11:25:24    

Ben, j'ai déjà tenté ce code comme indiqué dans le premier message :

Code :
  1. SELECT *, @num:=@num+1 as numero
  2.                     FROM $table_name as T1
  3.                     JOIN
  4.                         (SELECT max(id) as MaxId, ip, @num:=0 as numero
  5.                             FROM $table_name
  6.                             WHERE spider=''
  7.                             GROUP BY ip
  8.                             ORDER BY MaxId DESC LIMIT $LimitValue, $LIMIT
  9.                         ) as T2
  10.                     ON T1.ip = T2.ip
  11.                     HAVING numero < 20
  12.                     ORDER BY MaxId DESC, id DESC


Tentant de numéroter les lignes en partant de 0 pour chaque IP, mais cela ne fonctionne pas, cela incrémente toutes les lignes indépendamment des IP (s'il y a 1000 lignes, alors cela numérote jusqu'à 1000).
 
Merci encore !

Reply

Sujets relatifs:

Leave a Replay

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