【问题标题】:MySQL LEAST() with arbitrary number of parameters; longest match in a tableMySQL LEAST() 具有任意数量的参数;表中最长的匹配
【发布时间】:2016-05-24 13:07:16
【问题描述】:

我想创建一个 MySQL 查询来查找子网表中存在的最长匹配(以四点格式的给定 IP 地址)。

最终,我想创建一个LEFT JOIN,它将显示一个表中的每个四点 ip 地址以及另一个表中最长的匹配项。我不想创建任何临时表或将其构建为嵌套查询。

我有点像 MySQL 新手,但我的想法是这样的:

SELECT `ip_address`
  LEFT JOIN ON 
    SELECT `subnet_id`
    FROM `subnets_table`
    WHERE (`maximum_ip_value` - `minimum_ip_value`) =
    LEAST(<list of subnet intervals>)
      WHERE INET_ATON(<given ip address>) > `minimum_ip_value`
      AND INET_ATON(<given ip address>) < `maximum_ip_value`;

minimum_ip_valuemaximum_ip_value 是给定子网中可能的最低和最高十进制格式的 IP 地址 - 例如,对于子网 172.16.0.0/16:

minimum_ip_value = 2886729728 (or 172.16.0.0)
maximum_ip_value = 2886795263 (or 172.16.255.255)

&lt;list of subnet intervals&gt; 包含subnets_table 中的所有区间,其中&lt;given ip address&gt; 介于minimum_ip_valuemaximum_ip_value 之间

如果多个区间包含&lt;given ip address&gt;,则加入最小区间(即最小的子网,或最具体和“最长”的匹配)。

最终,我真正想要的是与该间隔对应的 subnet_id 值。

所以我的问题是:

1) 我可以使用带有任意数量参数的 LEAST() 函数吗?我想比较subnets_table的每一行,或者更具体地说,比较minimum_ip_valuemaximum_ip_value之间每一行的间隔,并选择最小的间隔。

2) 我可以在LEFT JOIN 查询中执行所有这些计算吗?我可以接受任何快速、封装并避免重复查询相同数据的建议。

我想知道这是否可以在单个查询中执行(即,不查询每个 IP 地址的子网表),但我不知道是否可以排除它。如果这看起来行不通,请告知,以便我尝试其他角度。

谢谢。

【问题讨论】:

  • 请将您的标签限制在您正在使用的 RDBMS 上。对于同一个问题,MySQL 和 SQL Server 通常需要不同的解决方案。

标签: mysql join network-programming longest-prefix


【解决方案1】:

经过一些研究和反复试验,我发现上面的原型查询存在一些问题:

LEAST() 函数只接受一定数量的参数。根据我最初的问题,我想要一个可以处理任意数量的参数或表中每一行的函数。这是 MySQL 中的一个不同的函数,MIN()

函数 MIN() 的优先级低于 MySQL 中的 JOIN 函数,并且在任何给定查询中在 JOIN 函数之后进行评估。因此,我不能在一组值的MIN()JOIN,因为在执行JOINMIN() 还不存在。

我认为解决此问题的唯一方法是执行两个单独的查询:一个使用 MIN(),首先执行,另一个使用 JOIN,对第一个查询的结果执行。这意味着对于具有 n 行的表,我将执行 n^n 查询,而不是 n查询。这是不可接受的。

为了解决这个问题,我编写了一个新脚本,在执行任何这些查询之前修改数据库。每个子网都有自己的 ip 值“桶”,并且该范围内的所有值都映射到该子网。如果更具体(即较小)的子网与不太具体(即较大)的子网重叠,则更具体的范围仅映射到较小的子网,而较大的子网仅保留来自不太具体的范围的值。现在任何给定的 IP 地址都只属于一个“桶”,并且只映射到一个子网,这是它最具体的匹配。我可以在这场比赛中JOIN,而不必担心MIN() 功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 2020-08-16
    相关资源
    最近更新 更多