MySQL - 帮助加入两个表

时间:2014-02-01 20:33:06

标签: mysql sql

我花了最近几天尝试加入这些表格,但我对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

2 个答案:

答案 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