2014-02-01 3 views
0

Я провел последние несколько дней, пытаясь присоединиться к этим таблицам, но мои знания о MySQL ограничены, и после поиска в Google я изо всех сил пытался найти подобную проблему, чтобы помочь решить мою проблему.MySQL - Помогите соединить две таблицы

В принципе, у меня есть 1 таблицу, которая хранит список IP-адресов, которые подключены к моему месту и я выбираю их следующим образом (playerIP является внутрибрюшинно в виде строки):

SELECT playerIP FROM playerLogin GROUP BY playerIP 

У меня также есть таблица, которая хранит IP-блоки страны, но они оптимизированы таким образом, чтобы выбрать страну из IP-вы делаете:

SELECT * FROM ipCountry WHERE ip < INET_ATON('127.0.0.1') ORDER BY ip DESC LIMIT 0, 1 

Без предела, она возвращает количество строк, но его первая строка, это страна для этого IP.

Я пытаюсь присоединиться к этим таблицам таким образом, чтобы у меня был первоначальный список IP-адресов из первого запроса, но также и страна для этого IP-адреса.

Любая помощь с оценкой,

Dave.

Edit:

В качестве примера, мой VPS находится во Франции, на IP '178.32.35.179' и следующий запрос:

SELECT * FROM ipCountry WHERE ip < INET_ATON('178.32.35.179') ORDER BY ip DESC LIMIT 0 , 5 

Возвращает 5 строк: IP Страна

- 2988441600 ~ fr 
- 2988179456 ~ se 
- 2987917312 ~ de 
- 2987915264 ~ it 
- 2987913216 ~ dk 

в случае, если первая строка возвращается Франция


Edit 2:

Образец начала таблицы ipCountry: внутрибрюшинно ~ страны

- 0 ~ us 
- 16777216 ~ au 
- 16777472 ~ cn 
- 16778240 ~ au 
- 16779264 ~ cn 
+0

просьбы указать, как сделаны ваши таблицы – CaSUaL

+0

Я получил таблицы IP страны от http://www.ip2nation.com/ –

ответ

0

Это, предполагают, чтобы быть чем-то вроде

SELECT p1.playerIP, p2.Country FROM playerLogin p1 
INNER JOIN ipCountry p2 ON p1.playerIP = p2.ip 

UPDATE: Grimrandomer, спасибо за Дополнительная информация. К сожалению, я не знаком с функцией inet_aton, но после прочтения этого (http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_inet-aton) Я думаю, что следующий может работать для вас:

SELECT p1.playerIP, p2.Country FROM playerLogin p1 
INNER JOIN ipCountry p2 ON INET_ATON(p1.playerIP) = p2.ip 

UPD 2: Что об этом:

SELECT p1.playerIP, p2.Country, MAX(p2.ip) FROM playerLogin p1 
    LEFT JOIN ipCountry p2 ON INET_ATON(p1.playerIP) > p2.ip 
GROUP BY 1, 2 
+0

Спасибо за ваше предложение, однако я не могу просто присоединиться к p1.playerIP и p2.ip, потому что player ip является строкой, а ip - числом для ip-блока, поэтому второй запрос получает первый блок с меньшим INET_ATON и ограничивает результаты к 1 :( –

+0

Не могли бы вы привести пример того, что вы называете ip-блоком? Мы можем попытаться разобрать его – IgorM

+0

Я отредактировал свой вопрос на примере таблицы countryIP, надеюсь, что это поможет :) –

1

Вы хотите сделать это как коррелированные подзапросы:

SELECT pl.playerIP, 
     (select c.country 
     from ipCountry c 
     where ip < INET_ATON(pl.playerIP) 
     order by ip desc 
     limit 1 
     ) as country 
FROM playerLogin pl 
GROUP BY playerIP; 

EDIT:

Смотрите, если эта версия работает быстрее:

SELECT playerIP, 
     (select c.country 
     from ipCountry c 
     where ip < theip 
     order by ip desc 
     limit 1 
     ) as country 
FROM (select distinct playerIP, INET_ATON(pl.playerIP) as theip 
     from playerLogin pl 
    ) pl; 

Возможно group by в результате подзапроса выполняется несколько раз для каждого IP.

И я предполагаю, что у вас уже есть индекс на ipCountry(ip, Country). Кроме того, не должно быть <=, а не <?

EDIT II:

Вы можете создать новую таблицу, используя тот же прием: limit 1

select country, ip, 
     (select min(ip) 
     from ipcountry ipc2 
     where ipc2.country <> ip.country and 
       ipc2.ip > ip.country 
     ) ipnext 
from ipcountry ipc; 

Положите это в таблице и построить индекс по (ip, ipnext, country).

Edit (Grimrandomer):

Я должен был использовать:

select country, ip, 
    (select ip 
    from ipcountry ipc2 
    where ipc2.ip > ipc.ip 
    ORDER BY ip LIMIT 0, 1 
    ) ipnext 
from ipcountry ipc ORDER BY ip 

, но это занимает всего 0,0012 секунды для всех 60,742 строк :)


написать запрос, как:

SELECT pl.playerIP, ipc.country 
FROM playerLogin pl join 
    ipcountry ipc 
    on pl.ipc >= ipc.ip and pl.ipc < ipc.ipnext 
GROUP BY playerIP; 

На самом деле, если у игроков есть много логинов, это может быть лучше использовать подзапрос:

SELECT pl.playerIP, ipc.country 
FROM (selectd distinct playerIP 
     from playerLogin pl 
    ) pl join 
    ipcountry ipc 
    on pl.ipc >= ipc.ip and pl.ipc < ipc.ipnext 
GROUP BY playerIP; 
+0

Мне нужно использовать 'order by ip DESC' для этого. Но у меня есть 3000+ IP-адресов в моей таблице, ограничивая этот запрос 0,100, он занимает 8,6138 секунд, как вы думаете, я должен оптимизировать это? –

+0

* Никто не должен делать что-либо * в качестве коррелированного подзапроса :-( – Strawberry

+0

100 строк занимает 8.7927 секунд, поэтому я не думаю, что это повлияло на улучшение, возможно, стоит изменить базу данных ipCountry, чтобы включить end ip, так что я могу сделать join on> low и <= high, что вы думаете? –

Смежные вопросы