【问题标题】:MySQL IP address camparing to ISPMySQL IP 地址露营到 ISP
【发布时间】:2013-03-14 18:11:09
【问题描述】:

我的 mySQL 数据库中有 2 个表。

第一个表是isp:

isp_ip_address | isp_name
-------------------------
157.55.33.0    | isp_3

157.55.0.0     | isp_1

193.219.9.0    | isp_2

65.55.213.0    | isp_4

195.182.85.226 | isp_5

78.58.5.117    | isp_6

78.58.5.0      |  isp_7

第二个表是user_stats:

uid | lastlogin_ip | lastlogin
------------------------------
111 | 78.58.83.111 | 2013-03-12

132 | 78.58.5.117  | 2013-03-12

258 | 195.182.85.226 | 2013-03-14

165 | 157.55.33.78  | 2013-03-12

822 | 65.55.213.216 | 2013-03-15

523 | 157.55.35.38 | 2013-03-12
.....

等等。

我需要比较用户 lastlogin_ip 和 isp_ip_address 并在新表中插入 uid、lastlogin_ip 和 isp_name。我需要像这样比较ip_address:如果完整的lastlogin_ip等于isp_ip_address然后停止搜索并写入isp_name,如果它们不匹配,我需要比较firdt 3部分IP地址并做同样的事情,如果3部分不匹配,我需要比较两部分IP地址并做同样的事情。

我尝试了以下 SQL 代码:

SELECT 
  user_stats.`uid`,
  user_stats.`lastlogin_ip`,
  isp.`isp`,
FROM
  stats.`user_stats` 
  LEFT JOIN stats.`isp` 
ON(
    IF(
      isp.isp_ip_address LIKE user_stats.`lastlogin_ip`,
      isp.isp_ip_address LIKE user_stats.`lastlogin_ip`,
      IF(
        SUBSTRING_INDEX(isp.isp_ip_address,'.',-1) LIKE SUBSTRING_INDEX(user_stats.`lastlogin_ip`,'.',-1),
        IF(
          SUBSTRING_INDEX(SUBSTRING_INDEX(isp.isp_ip_address,'.',3),'.',-1) LIKE SUBSTRING_INDEX(SUBSTRING_INDEX(user_stats.`lastlogin_ip`,'.',3),'.',-1),
          IF(
            SUBSTRING_INDEX(SUBSTRING_INDEX(isp.isp_ip_address,'.',2),'.',-1) LIKE SUBSTRING_INDEX(SUBSTRING_INDEX(user_stats.`lastlogin_ip`,'.',2),'.',-1),
            SUBSTRING_INDEX(isp.isp_ip_address,'.',1) LIKE SUBSTRING_INDEX(user_stats.`lastlogin_ip`,'.',1),
            NULL),
          SUBSTRING_INDEX(isp.isp_ip_address,'.',2) LIKE SUBSTRING_INDEX(user_stats.`lastlogin_ip`,'.',2)),
        SUBSTRING_INDEX(isp.isp_ip_address,'.',3) LIKE SUBSTRING_INDEX(user_stats.`lastlogin_ip`,'.',3))));

此代码比较部分 IP 地址,但它重复了行,这意味着如果它找到 3 个相等的部分和 2 个相等的部分,它会使用不同的 isp_name 值将同一行写入两次。

您能否给我一个提示,我应该如何编辑此代码以使其正常工作? 任何帮助将不胜感激!

【问题讨论】:

    标签: mysql sql if-statement ip-address


    【解决方案1】:

    非常未经测试,但希望能让您走上正轨:

    编辑:qry 已修复语法并经过测试。

    选择 match3.lastlogin_ip, ifnull(match3.isp_name, isp.isp_name) as isp_name FROM (SELECT match4.lastlogin_ip, ifnull(match4.isp_name, isp.isp_name) as isp_name, isp.isp_ip_address FROM (从 user_stats 中选择 user_stats.lastlogin_ip、isp.isp_name、isp.isp_ip_address LEFT JOIN isp ON (user_stats.lastlogin_ip = isp.isp_ip_address)) 作为 match4 LEFT JOIN isp ON (match4.isp_name is null and SUBSTRING_INDEX(match4.lastlogin_ip,'.', 3) = SUBSTRING_INDEX(isp.isp_ip_address,'.', 3))) as match3 LEFT JOIN isp ON (match3.isp_name 为空并且 SUBSTRING_INDEX(match3.lastlogin_ip,'.', 2) = SUBSTRING_INDEX(isp.isp_ip_address,'.', 2));

    【讨论】:

    • 我编辑了您的查询(存在一些语法错误),但此查询仅将 isp_name 提供给 ip_addresses 由所有 4 个部分相等的行。 3部分,2部分和其他行为NULL
    • 这看起来就是您所要求的:“所有 4 个部分相等。3 个部分,2 个部分”。缺少什么?
    • 我找不到问题所在。但是当我运行这个查询时,它只显示 ip_adress 和 lastlogin 的所有 4 个部分都相等的 isp_names。当 3 或 2 部分相等时,查询不写 isp_name 而是写 NULL 值
    • 好的,从您的第一条评论中并不清楚 isp_name 对于 2&3 匹配项是否为空。与 isp 不匹配的行确实应该将 isp_name 返回为 NULL。请用你的语法正确的 SQL 编辑我的答案,我会看看它。
    • 我已经修复了语法错误并稍微更改了一些标准,只是为了便于阅读。该查询根据您的解释工作。请注意,您的示例中的 uid=111 和 uid=523 将按预期分别获得两个 isp,因为那里可能缺少一些 isp 记录。
    【解决方案2】:

    将 IP 地址和 CIDR 存储为整数然后使用类似这样的东西不是更好吗:Is there way to match IP with IP+CIDR straight from SELECT query?

    1. 阅读这些查询更容易
    2. 可能比您目前拥有的更快
    3. 比较比子字符串比较更准确(在网络方面)。

    【讨论】:

      【解决方案3】:

      您的加入条件与您的描述不符。当与负数一起使用时,substring_index 返回 ip 的右侧,而不是左侧。

      无论如何,请尝试以下连接条件(未经测试):

      ON(
         isp.isp_ip_address = user_stats.lastlogin_ip
      OR SUBSTRING_INDEX(isp.isp_ip_address,'.', 3) = SUBSTRING_INDEX(user_stats.lastlogin_ip,'.', 3)
      OR SUBSTRING_INDEX(isp.isp_ip_address,'.', 2) = SUBSTRING_INDEX(user_stats.lastlogin_ip,'.', 2)
      )
      

      【讨论】:

      • 此连接条件仍然重复行。例如,如果我的 IP 地址为 78.58.5.117,它将用 isp_name isp_7 写入一次,用 isp_name isp_6 写入一次,因为 isp_name -> isp_7 具有 isp_ip_address -> 78.58.5.0(3 部分相等)和 isp_name -> isp_6具有 isp_ip_address -> 78.58.5.117(所有 4 个部分都相等)。如果 78.58.5.117 = 78.58.5.117 或不相等,我只需要插入一次,尝试比较 IP 地址 78.58.5.% = 78.58.5.% 的前 3 部分,如果不相等,请尝试比较前 2零件 78.58.%.% = 78.58.%.%
      • 我明白了。这不能通过单个连接来完成,因为连接一次只比较每个表中的一条记录。在您的情况下,由于子/超级 isps 涉及多个记录。三个组合中的每一个都需要子查询,然后部分连接以选择相关记录。如果您需要,我稍后会尝试提供更完整的答案。
      • 如果您能为我提供更完整的答案,那就太好了,因为我已经对如何编写此查询的想法感到空虚
      猜你喜欢
      • 1970-01-01
      • 2021-02-26
      • 2021-10-22
      • 2015-05-11
      • 2012-07-25
      • 1970-01-01
      • 2013-09-21
      • 1970-01-01
      • 2021-01-10
      相关资源
      最近更新 更多