2010-11-20 9 views
0

J'ai une table de visite (de visit_table), structure:MySQL - comment GROUPER par le résultat d'une autre requête?

  • ID
  • IP_address
  • timestamp

et une table (country_table) avec des noms de pays pour les plages IP

  • ID
  • begin_IP (début de la plage d'adresses IP)
  • de end_IP (fin de la plage d'adresses IP)
  • de begin_num (l'équivalent numérique de begin_IP, à savoir INET_ATON (begin_IP))
  • END_NUM
  • country_code (par exemple, US)
  • country_name
    (basé sur http://www.maxmind.com/app/csv)

J'utilise MySQL 5.0.67 et je voudrais écrire une requête pour renvoyer le nombre de visites par pays, donc quelque chose le long des lignes de:

SELECT country.table.country_name, 
     count(distinct visit_table.IP_address) 
    FROM country_table, visit_table 
    WHERE country_name = (SELECT country_name 
          FROM country_table 
          WHERE INET_ATON(visits.IP_address) >= begin_num 
          AND INET_ATON(visits.IP_Address) <= end_num 
          LIMIT 0,1) 
GROUP BY country_table.country_name 

Je suis sûr que je fais quelque chose de mal, mais ne savent pas comment résoudre - une sorte de JOIN ou de faire quelque chose avec le SELECT ou GROUP BY? Tous les pointeurs sont les bienvenus!

+0

Je pense que vous pouvez écrire une instruction select dans le groupe par clause sous la forme d'un sous-sélection. Cela fonctionne sur Oracle, peut-être que cela fonctionne aussi sur mysql. Quelqu'un peut-il confirmer cela? – Falcon

Répondre

1

Oui vous voulez une jointure:

SELECT country_table.country_name, count(distinct visit_table.IP_address) 
FROM country_table 
RIGHT JOIN visit_table ON visit_table.id=country_table.id  
GROUP BY country_table.country_name 
3

Utilisation:

SELECT c.country_name, 
     COUNT(DISTINCT v.IP_address) 
    FROM COUNTRY_TABLE c 
    JOIN VISIT_TABLE v ON v.country_name = c.country_name 
    WHERE INET_ATON(v.IP_Address) BETWEEN begin_num AND end_num 
GROUP BY c.country_name 

S'il n'y a pas de pays pour cette plage d'adresses IP, vous ne tirerez rien. Mais s'il y a plus d'un pays renvoyé de la plage, la requête doit être mise à jour pour la gérer.

Si vous voulez un pays qui pourrait ne pas avoir des adresses IP capturées pour, utilisez:

SELECT c.country_name, 
      COUNT(DISTINCT v.IP_address) 
    FROM COUNTRY_TABLE c 
LEFT JOIN VISIT_TABLE v ON v.country_name = c.country_name 
    WHERE INET_ATON(v.IP_Address) BETWEEN begin_num AND end_num 
GROUP BY c.country_name 
+0

Un groupe de c.country_code serait-il plus rapide? – Pentium10

+0

@ Pentium10: Le regroupement ou l'association par type de données qui utilise moins d'octets pour stocker la valeur devrait être plus performant. Un index peut être considéré, mais aura un impact négatif sur les requêtes INSERT/UPDATE/DELETE ... –

Questions connexes