我花了最近几天尝试加入这些表格,但我对MySQL的了解有限,在搜索谷歌之后,我一直在努力寻找类似的问题来帮助解决我的问题。
基本上,我有一个表存储已连接到我的站点的IP地址列表,我按如下方式选择它们(playerIP是ip作为字符串):
SELECT playerIP FROM playerLogin GROUP BY playerIP
我还有一个存储国家/地区IP块的表,但它们以这样的方式进行了优化,以便选择您所在的国家/地区:
SELECT * FROM ipCountry WHERE ip < INET_ATON('127.0.0.1') ORDER BY ip DESC LIMIT 0, 1
没有限制,它会返回许多行,但它是该IP的国家/地区的第一行。
我试图以这样的方式加入这些表格,以便我从第一个查询中获得原始的IP列表,但同时拥有该IP的国家/地区。
任何帮助表示赞赏,
戴夫。
编辑:
作为一个例子,我的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 country
- 2988441600 ~ fr
- 2988179456 ~ se
- 2987917312 ~ de
- 2987915264 ~ it
- 2987913216 ~ dk
第一个返回的行是法国
编辑2:
ipCountry表的开头示例: ip~country
- 0 ~ us
- 16777216 ~ au
- 16777472 ~ cn
- 16778240 ~ au
- 16779264 ~ cn
答案 0 :(得分:2)
您希望将此作为相关子查询执行:
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;
编辑:
查看此版本是否运行得更快:
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)
的索引。此外,它不应该是<=
而不是<
?
编辑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)
上建立索引。
编辑(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
但是对于所有60,742行,这只需要0.0012秒:)
将您的查询写为:
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;
答案 1 :(得分:0)
它假设是
SELECT p1.playerIP, p2.Country FROM playerLogin p1
INNER JOIN ipCountry p2 ON p1.playerIP = p2.ip
更新: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