1

同じスキームと列を持つ2つのmysqlテーブルを比較しようとしています。このテーブルには、IPアドレス、IPアドレスが通信するポート、IPアドレスがインまたはアウトバウンドであるかどうか、および1か月間の接続数が含まれています。以下は、数字で構成された小さなサンプルテーブルです(実際のテーブルは約10万行です)。

+---------------+------+----------+-------------+-----------+
| 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、ポート、プロト、方向の組み合わせが新しい/存在しないことを確認し、一致する場合は接続数の変化を確認することです。

私の当初の考えは、単に各行をループしてから、他のテーブルに対してクエリを実行して、その接続が存在するかどうかを確認することでしたが、これにより、文字通り数十万のクエリが実行されます。これを行うにはもっと簡単な方法が必要だと私は感じています。(以下の例)

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";
    }
  }
}
4

2 に答える 2

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
)

Febこれで、 に一致しないものすべてのリストができましたmonth2(つまり、2 月には「新規」です)。

于 2012-05-02T21:11:08.047 に答える
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がサブクエリ列に s を持つためです。

于 2012-05-02T21:18:10.783 に答える