Comment créer une table de données temporaire avec WordPress ? (Créer un compte)

  • Statut : non résolu
15 sujets de 1 à 15 (sur un total de 15)
  • Auteur
    Messages
  • #505818
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Bonjour,

    Ma configuration WP actuelle
    – Version de WordPress :
    – Version de PHP/MySQL :
    – Thème utilisé :
    – Extensions en place :
    – Nom de l’hebergeur :
    – Adresse du site :

    Problème(s) rencontré(s) :

    Bonjour,
    Pour un plugin (Statpress-visitors) que j’entretiens, j’ai besoin de faire un tri sur deux critères : c’est à dire afficher les 20 dernières visites des 20 dernières IP. Ce qui correspond à la fonction SPY (log des visites).

    Autant, il est facile de coder cela en PHP, autant créer une requête SQL qui renvoit uniquement ces résultats là est difficile. En effet, la clause SQL LIMIT agit sur la totalité des résultats de la requête et il n’est pas possible de faire agir en MySql le LIMIT d’abord sur les IP et ensuite un autre LIMIT sur les dernières visites.

    Faire ce double tri en MySql est vraiment très difficile à réaliser.

    J’ai trouvé une requête utilisant une auto jointure qui renvoit TOUTES les visites des 20 dernières IP, mais certaine IP ont beaucoup de visites et ainsi pour afficher les 20 dernières visites des 20 dernières IP, cette requête renvoit 1000 lignes pour une table de données de 150 000 lignes en 1,6 sec. Ce qui n’est pas catastrophique avec une table de données non optimisée comme elle l’est actuellement.
    Là où cela devient catastrophique, c’est lorque l’on traite en PHP ces 1000 lignes renvoyées par la requête, cela prend en local 30 secondes !:fouet:

    PHP n’étant pas un langage compilé, le traitement d’un grand nombre de données est très lourd et très lent. Alors que MySQL est adapté au traitement d’un grand nombre de données mais ne permet pas de faire un double tri !😉

    Alors, j’ai cherché une autre requête, en vain et finalement je m’oriente vers la création d’une table temporaire, cette table contenant les résultats de la requête précédente. Interroger cette table devient alors très rapide tant en MySQL qu’en PHP…

    Mais apparemment, il est impossible de créer des tables de données temporaire avec WordPress, quelqu’un a-t-il une idée de comment créer malgré tout une table de données temporaire sous WordPress, même si on n’utilise pas les fonctions standard de WordPress.

    La requête de création de la table temporaire en SQL est alors (id est l’index primaire de la table $table_name) :

    CREATE TEMPORARY TABLE « .$table_spy. » AS (SELECT *
    FROM $table_name as T1
    JOIN
    (SELECT max(id) as MaxId,ip
    FROM $table_name
    WHERE spider= »
    GROUP BY ip
    ORDER BY MaxId DESC LIMIT $LimitValue, $LIMIT
    ) as T2
    ON T1.ip = T2.ip
    ORDER BY MaxId DESC, id DESC;
    )

    Si quelqu’un a une idée, merci !

    #817405
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Pour l’instant, je ne vois pas d’autres issues que d’utiliser les fonctions PHP prévues pour interagir avec une base de données :
    http://www.php.net/manual/fr/book.mysql.php

    Mais la fonction de connection à une base de données nécessite des paramètres comme le nom d’hôte etc, où les trouve-t-on ? Ou alors s’agit-il de variable globale définies dans wp-config.php ?
    http://www.php.net/manual/fr/function.mysql-connect.php

    #817416
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Bon,
    pour l’instant, j’ai créé des fonctions de connection et de déconnection à la base de données qui fonctionnent :

    function connect_bd() 
    {
    $nomserveur=DB_HOST; //nom du seveur
    $nombd=DB_NAME; //nom de la base de données
    $login=DB_USER; //login de l’utilisateur
    $pass=DB_PASSWORD; // mot de pass
    $bd=mysql_connect($nomserveur, $login, $pass)or die(« Connexion échouée »);
    mysql_select_db($nombd,$bd)or die(« La base ne peut pas être selectionnée »);
    return $bd;
    }

    function deconnect_bd($bd)
    {
    mysql_close($bd);
    $db=0;
    }

    Ainsi que la requête qui crée cette table temporaire, j’ai du renommer le deuxième champs ip en ip1 car sinon, cela ne fonctionne pas :

    $result = mysql_query(« CREATE TEMPORARY TABLE « .$table_spy. » AS (SELECT *
    FROM $table_name as T1
    JOIN
    (SELECT max(id) as MaxId,ip as ip1
    FROM $table_name
    WHERE spider= »
    GROUP BY ip
    ORDER BY MaxId DESC LIMIT $LimitValue, $LIMIT
    ) as T2
    ON T1.ip = T2.ip1
    ORDER BY MaxId DESC, id DESC) »);

    J’ai pu interroger cette table temporaire, cela fonctionne…
    Reste plus qu’à modifier tout le code du plugin pour utiliser cette table temporaire !

    #817417
    Lumiere de Lune
    Participant
    Maître WordPress
    20531 contributions

    Il est très facile d’insérer une requête mysql à l’intérieur d’une requete
    requete A = selectionner les 20 dernières ip
    requete B = selectionner les 20 dernières visites where ip in requete A (suffit de mettre le texte de requete A à la place)

    #817406
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Je dois alors mal comprendre, car lorsque je fais un LIMIT 20 ip cela n’affiche que les 20 dernières visites totales.

    Et quand je fais un IN requêtes A comme vous dites, cela m’indique l’erreur suivante : « votre version de MySql ne permet pas d’avoir un LIMIT dans un IN !

    #817407
    Lumiere de Lune
    Participant
    Maître WordPress
    20531 contributions

    Ah … ça c’est dommage

    #817408
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Oui, c’est dommage, voilà l’erreur exacte « #1235 – This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME subquery’

    Le pire, c’est que d’après mes premiers tests, la table temporaire n’améliore pas les performances de la page, le temps passé en PHP sur 1000 lignes est remplacé par le temps de faire les 20 requêtes sur la table temporaire pour les 20 dernières ip…

    Bref, c’est la galère !

    #817409
    Guy
    Participant
    Maître WordPress
    14817 contributions

    bon… c’est vrai que l’on ne peut pas et j’avais contourné avec un inner join et des cabrioles, mais ton idée de table secondaire me fait penser que l’on peut peut être créer une requête avec un alias et un as:

    faut voir si ça marche.

    requete A = selectionner les 20 dernières ip
    requete B = selectionner les 20 dernières visites where ip in ( select * from (requete A) as temp)

    #817410
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Je fais les essais, merci de l’idée !:D

    #817411
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Si j’écris la requête ainsi :

    SELECT *
    FROM wp_statpress
    WHERE ip IN
    ((SELECT ip
    FROM wp_statpress
    WHERE spider= »
    GROUP BY ip LIMIT 0,20
    ) as T)
    ORDER BY ip, id DESC

    Cela m’indique l’erreur suivante :
    #1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘as T) ORDER BY ip, id DESC

    Quelle était votre autre façon de faire avec un INNER JOIN et des cabrioles ? On sait jamais…

    #817412
    Guy
    Participant
    Maître WordPress
    14817 contributions

    oula, je ne sais plus ou c’est :(

    mais sinon, ce n’était pas exactement ce que j’avais mis pour la requête (et cette syntaxe est correcte si les champs existent)

    SELECT *
    FROM wp_statpress
    WHERE ip
    IN (
    SELECT *
    FROM (
    SELECT ip
    FROM wp_statpress
    WHERE spider= »
    GROUP BY ip
    LIMIT 0 , 20
    ) AS T
    )
    ORDER BY ip, id DESC
    LIMIT 0 , 30

    #817413
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Ah oui effectivement, en faisant comme vous le dites il n’y a pas d’erreurs MySQL, seulement, le tri n’est plus fait dans le bon ordre, certaines IP vues en août 2011 apparaissent comme postérieures à celles de 2012.
    De plus les 4 premières IP qui apparaissent n’existent même pas dans la base de données, c’est vraiment étrange.
    J’ai dû faire une erreur dans ma requête que voici :

    $sql = « SELECT *
    FROM $table_name
    WHERE ip
    IN (SELECT *
    FROM (SELECT ip
    FROM $table_name
    WHERE spider= »
    GROUP BY ip
    LIMIT $LimitValue, $LIMIT
    ) AS T1
    )
    ORDER BY ip, id DESC »;
    $qry = $wpdb->get_results($sql);

    #817414
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Ah oui, j’ai pigé, c’est le ORDER BY IP qui fait que les IP sont rangées dans l’ordre croissant des IP de la plus petite IP à la plus grande !

    #817415
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    Mais même en supprimant le ORDER BY ip, je perd le rangement des visites de la plus récente à la plus vieille, je n’arrive plus à les classer dans le bon ordre.
    C’est le MaxId qui me sert à les ranger dans le bon ordre dans ma première requête. Elle sont rangées selon le MaxId qui est le même pour toutes les IP identiques.
    Mais je ne peux pas utiliser le IN avec deux valeurs IP et MaxId.

    Je crois que je suis à nouveau bloqué !
    😉

    #817418
    luciole135
    Participant
    Maître WordPress
    13714 contributions

    J’ai tenté une nouvelle requête pensant numéroter chaque ligne retournée par la requête.
    J’aurais voulu que pour chaque IP le numérotage parte de zéro, mais cela ne fonctionne pas, les lignes sont numérotées de 1 à 1000 s’il y en a mille indépendamment des IP.
    Voilà la requête :

    $sql = « SELECT *, @num:=@num+1 as numero
    FROM $table_name as T1
    JOIN
    (SELECT max(id) as MaxId, ip, @num:=0 as numero
    FROM $table_name
    WHERE spider= »
    GROUP BY ip
    ORDER BY MaxId DESC LIMIT $LimitValue, $LIMIT
    ) as T2
    ON T1.ip = T2.ip
    HAVING numero < 20
    ORDER BY MaxId DESC, id DESC
    ";

    Et ainsi, il n’y a que 20 lignes au total qui sont affichées.
    Je me demande s’il est possible seulement de faire un double tri en MySql sans faire un premier tri sur le premier critère et autant de tris pour le deuxième critère que de résultats dans le premier tri.

15 sujets de 1 à 15 (sur un total de 15)
  • Vous devez être connecté pour répondre à ce sujet.