使用perl比较2个mysql表而不更新或组合

时间:2012-05-02 21:07:44

标签: mysql perl

我正在尝试将2个mysql表与相同的方案和列进行比较。该表包含IP地址,它们通信的端口,是否在入站或出站以及1个月内的连接数。下面是一个带有编号的小例子表(实际表格大约是100k行)。

+---------------+------+----------+-------------+-----------+
| ip_address    | port | protocol | connections | direction |
+---------------+------+----------+-------------+-----------+
| 123.17.19.6    | 123  | 17       | 31972       | IN        |
| 123.17.19.6    | 22   | 6        | 4           | IN        |
| 123.17.19.6    | 25   | 6        | 206969      | IN        |
| 123.17.19.10   | 135  | 6        | 2997        | OUT       |
| 123.17.19.10   | 389  | 17       | 4965        | OUT       |
| 123.17.19.10   | 389  | 6        | 7089        | OUT       |
| 123.17.19.11   | 139  | 6        | 1           | OUT       |
| 123.17.19.10   | 135  | 6        | 1102        | OUT       |
| 123.17.19.11   | 389  | 17       | 2993        | OUT       |
| 123.17.19.11   | 389  | 6        | 1629        | OUT       |
| 123.17.19.11   | 443  | 6        | 28          | OUT       |
| 123.17.19.11   | 445  | 6        | 4267        | OUT       |
| 123.17.19.11   | 53   | 17       | 5230        | OUT       |
| 123.17.19.11   | 53   | 6        | 10          | OUT       |
| 123.17.19.11   | 80   | 6        | 11          | OUT       |
| 123.17.19.12   | 135  | 6        | 1640        | OUT       |
| 123.17.19.12   | 22   | 6        | 2           | OUT       |
| 123.17.19.10   | 22   | 6        | 6           | OUT       |
| 123.17.19.12   | 389  | 17       | 2539        | OUT       |
+---------------+------+----------+-------------+-----------+

我想要做的是比较2个月,看看IP,Port,Proto&方向组合是新的/不再存在,对于任何匹配,都可以看到连接数的变化

我最初的想法只是循环遍历每一行,然后针对另一个表运行查询以查看该连接是否存在,但这将导致运行数十万个查询。我觉得必须有一个更简单的方法来做到这一点。 (以下示例)

use strict;
use warnings;
use DBI;

my ($db1_list,$db2_list,@compare_list1,@compare_list2);
my $db1 = "Jan";
my $db2 = "Feb";

$db2_list = login()->prepare(qq(select * from $db2));
$db2_list->execute;

while (@compare_list2 = $db2_list->fetchrow()){
  $db1_list = login()->prepare(qq(select * from $db2 where ip_address = "@compare_list2[0]" and port = @compare_list2[1] and protocol = @compare_list2[2] and direction = "@compare_list2[4]"));
  $db1_list->execute;

  while (@compare_list1 = $db1_list->fetchrow()){
    if (@compare_list1[0] ~~ @compare_list2[0]);
      @compare_list[3] -= @compare_list[3];
      print "@compare_list[3]\n";
    }
    else {
      print "@compare_list2[0], @compare_list2[1], @compare_list2[2], @compare_list2[3], @compare_list2[4] was seen in $db2 and not in $db1\n";
    }
  }
}

2 个答案:

答案 0 :(得分:3)

MySQL可以在一个查询中执行此操作:

SELECT *
FROM Feb
WHERE NOT EXISTS (SELECT 1 FROM Jan
    WHERE Feb.ip = Jan.ip
    AND Feb.protocol = Jan.protocol
    AND Feb.direction = Jan.direction
)

现在你已经列出了Febmonth2中没有匹配项的所有内容(所以2月份是“新”)。

答案 1 :(得分:1)

问题1:获取匹配的行。

这将返回所有比较列的值相同的行:

select * 
from table1
inner join table2
using (... column names ...);

select * 
from table1
inner join table2
on table1.<field> = table2.<field> and ...;

问题2:

您可以使用第1部分作为子查询来实现关系减法,回答“哪些行是新的/缺失的”问题:

select * 
from table1
left join ( ... subquery ...) as sq
on ... join condition ...
where ... <some fields in the subquery are null>;

这是有效的,因为table中子查询中没有匹配项的行在子查询列中将有NULL个。