【问题标题】:Join 2nd Table with Less Than, Order Desc Query加入小于号的第二个表,订单描述查询
【发布时间】:2013-05-06 09:10:58
【问题描述】:

我有一个记录对我网站的访问的博客:

Table weblog
id  logdate    browser  ipaddr         inet_aton_ip
 1  2013-05-01 Chrome   42.61.66.124      708657788
 2  2013-05-01 Chrome   217.9.192.99     3641294848
 3  2013-05-02 Firefox  77.79.58.77      1297037901
...etc...

我下载了 ip2nation 数据库,它可以让我根据 inet_aton_ip 值查找国家/地区:

mysql> select * from ip2nation where ip<708657788 order by ip desc limit 1;
+-----------+---------+
| ip        | country |
+-----------+---------+
| 708575232 | sg      |
+-----------+---------+
mysql> select * from ip2nation where ip<3641294848 order by ip desc limit 1;
+------------+---------+
| ip         | country |
+------------+---------+
| 3641286656 | uk      |
+------------+---------+
... and so on ...

ip2nation 中的 ip 列标记了 IP 边界,因此搜索不精确,即无法进行相等比较。这种结构是有道理的,对于像 42.61.66.x 这样的子网,它们不必列出 255 个类似的条目。

使用类似的 C# 例程

DataTable dt = [a sql function to select * from weblog]
foreach (DataRow row in dt.Rows)
{
     long ipnum = int.Parse(row["inet_aton_ip"].ToString());
     string cty = [a sql function to select country using ipnum]
}

我可以得到下表:

id  logdate    browser  ipaddr         inet_aton_ip  country
 1  2013-05-01 Chrome   42.61.66.124      708657788  sg
 2  2013-05-01 Chrome   217.9.192.99     3641294848  uk
 3  2013-05-02 Firefox  77.79.58.77      1297037901  lt

我想知道我是否可以像在 C# 例程中那样使用一个 sql 而不是两个 sql 来生成上表?我尝试使用子选择和连接,但每次我都被“ip小于x order by ip desc limit 1”部分所抛弃。希望在这里得到 SQL 专家的任何指点。

【问题讨论】:

    标签: mysql sql join


    【解决方案1】:

    如果我们有 ip2nation 表,那么您可以像这样连接两个表:

    SELECT w.*, ip.country
      FROM weblog w
      JOIN ip2nation ip
        ON w.inet_aton_ip = ip.ipp
    

    输出:

    ╔════╦════════════════════════════╦═════════╦══════════════╦══════════════╦═════════╗
    ║ ID ║          LOGDATE           ║ BROWSER ║    IPADDR    ║ INET_ATON_IP ║ COUNTRY ║
    ╠════╬════════════════════════════╬═════════╬══════════════╬══════════════╬═════════╣
    ║  1 ║ May, 01 2013 00:00:00+0000 ║ Chrome  ║ 42.61.66.124 ║    708657788 ║ sg      ║
    ║  2 ║ May, 01 2013 00:00:00+0000 ║ Chrome  ║ 217.9.192.99 ║   3641294848 ║ uk      ║
    ║  3 ║ May, 02 2013 00:00:00+0000 ║ Firefox ║ 77.79.58.77  ║   1297037901 ║ lt      ║
    ╚════╩════════════════════════════╩═════════╩══════════════╩══════════════╩═════════╝
    

    See this SQLFiddle

    【讨论】:

    • 不幸的是,使用 equal 不起作用,因为 ip2nation 表是按范围排序的,这可能不会导致完全匹配。
    • 不幸的是,使用 equal 不起作用,因为 ip2nation 表是按范围排序的,这可能不会导致完全匹配。例如,ip2nation 可能包含行“708000000,sg”和“709000000,th”。那么对于 708657788 的相等比较将失败。但是使用语句“ip
    • 博客表结构与我在问题中显示的一样。 ip2nation 是一个包含 2 列(ip、国家)的表。 “select * from ip2nation limit 5”返回:(ip, country), (0, 'us'), (687865856, 'za'), (689963008, 'eg'), (691011584, 'za'), (691617792,'zw')。 ip2nation 表是一个开源表,可以从网上下载。
    • @DavidOng - 如果表ip2nationip 列仅包含691617792 之类的整数,则此查询将完美运行。
    • 这也是我最初的方法。但是在阅读了 ip2nation 技术说明之后,我意识到 ip 整数标记了边界,而不是确切的 ip。这是有道理的,因为像 46.61.66.x 这样的子网可以包含 255 个单独的 ip。参考我上面两个帖子的回答,我们有 ip=687865856 => 'za', ip=689963008 => 'eg'。如果我得到一个 ip=689000000,它在表中没有完全匹配。但是使用“ip小于x order by ip desc limit 1”规则,我们最终得到ip=689000000 => 'za'。所以我很欣赏这个答案,但不幸的是,情况更复杂。
    【解决方案2】:

    您可以通过使用INNER JOIN 直接加入表ip2nation 来获取country

    SELECT  a.*. b.country
    FROM    weblog a
            INNER JOIN ip2nation b
                ON a.inet_aton_ip = b.ipp
    WHERE   b.ipp < 708657788 
    order   by b.ipp
    

    如需进一步了解联接,请访问以下链接:

    【讨论】:

    • 这仅适用于第一行博客。第二行和第三行有不同的数字:分别为 3641294848 和 1297037901。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 2019-08-02
    • 2022-11-30
    • 1970-01-01
    相关资源
    最近更新 更多