1

iphdr2 つのフィールドがip_srcあり、ip_dstIP を数値 (inet_aton) 形式で格納するという名前のテーブルがあります。Web アプリケーションで最も頻繁に発生する送信元、送信先、および (送信元 + 送信先) IP を取得する必要があります。ピラミッドで SQLalchemy を使用しています。

頻繁に発生する送信元/宛先 IP

これは簡単な部分です。グループをカウントして結果を取得するだけです

mysql> select inet_ntoa(ip_dst) as ip,count(*) as count1 from iphdr group by ip;
+--------------+--------+
| ip           | count1 |
+--------------+--------+
| 192.168.1.22 |     13 |
| 192.168.2.8  |      1 |
| 31.1.1.22    |      1 |
| 31.21.18.100 |    905 |
| 31.21.18.221 |      4 |
+--------------+--------+
5 rows in set (0.00 sec)

SQLAlchemy の対応するステートメントは

>>>top_srcs = session.query(func.inet_ntoa(IpHdr.ip_dst).label('ip'),func.count('*').label('ip_count')).group_by('ip').order_by(desc('ip_count'))
>>>print top_srcs.all()
[('31.21.18.100', 905L), ('192.168.1.22', 13L), ('31.21.18.221', 4L), ('192.168.2.8', 1L), ('31.1.1.22', 1L)]

カウントでソートされた頻繁に発生する Src+Dest

MySQL では、union all を使用して個々の src/dest クエリを結合することで、これを簡単に行うことができます。

mysql> select 
m.ip,sum(m.count1) as c 
from 
(
select 
inet_ntoa(ip_dst) as ip,count(*) as count1 
from iphdr group by ip 
union all 
select 
inet_ntoa(ip_src) as ip,count(*) as count1 
from iphdr group by ip
) 
as m  group by m.ip order by c desc;
+---------------+------+
| ip            | c    |
+---------------+------+
| 31.21.18.100  |  924 |
| 192.168.2.10  |  186 |
| 31.21.18.101  |  171 |
| 192.168.2.9   |  165 |
| 192.168.2.8   |   96 |
| 192.168.2.4   |   84 |
| 192.168.2.5   |   78 |
| 192.168.2.6   |   38 |
| 192.168.1.22  |   31 |
| 31.1.1.9      |   25 |
| 31.11.100.101 |   17 |
| 192.168.2.7   |   17 |
| 31.21.18.221  |    6 |
| 192.168.33.10 |    6 |
| 31.1.1.22     |    4 |
+---------------+------+
15 rows in set (0.01 sec)

しかし、SQLALchemy では、2 つのステートメントを同じ方法で結合しようとすると、さまざまなエラーが発生します。

top_srcs = session.query(func.inet_ntoa(IpHdr.ip_src).label('ip'),func.count('*').label('ip_count')).group_by('ip').order_by(desc('ip_count'))
    top_dsts = session.query(func.inet_ntoa(IpHdr.ip_dst).label('ip'),func.count('*').label('ip_count')).group_by('ip').order_by(desc('ip_count'))

mod_top_srcs = top_srcs.subquery().select()
mod_top_dsts = top_dsts.subquery().select()
x = union_all(mod_top_srcs,mod_top_dsts).select()
top_total = session.query(x).group_by('ip').order_by(desc('total'))

OperationalError: (OperationalError) (1248, 'Every derived table must have its own alias

このスレッドを見ましたが、解決策がうまくいきません

編集

私はエイリアスをいじって(それが最初のエラーだったので)、次のステートメントを書くことができました

>>>ts = top_srcs.subquery().select()
>>>td = top_dsts.subquery().select()
>>>session.query('ip','ip_count').select_from(union_all(ts,td).alias('mno').select().alias('abc')).all()
[('192.168.2.10', 186L), ('31.21.18.101', 171L), ('192.168.2.9', 165L), ('192.168.2.8', 95L), ('192.168.2.4', 84L), ('192.168.2.5', 78L), ('192.168.2.6', 38L), ('31.1.1.9', 25L), ('31.21.18.100', 19L), ('192.168.1.22', 18L), ('31.11.100.101', 17L), ('192.168.2.7', 17L), ('192.168.33.10', 6L), ('31.1.1.22', 3L), ('31.21.18.221', 2L), ('31.21.18.100', 905L), ('192.168.1.22', 13L), ('31.21.18.221', 4L), ('192.168.2.8', 1L), ('31.1.1.22', 1L)]

しかし、合計を取得しようとすると、それが壊れます

>>> session.query('ip',sum('ip_count')).select_from(union_all(ts,td).alias('mno').select().alias('abc')).group_by('abc.ip').all()
[('192.168.1.22', 0.0), ('192.168.2.10', 0.0), ('192.168.2.4', 0.0), ('192.168.2.5', 0.0), ('192.168.2.6', 0.0), ('192.168.2.7', 0.0), ('192.168.2.8', 0.0), ('192.168.2.9', 0.0), ('192.168.33.10', 0.0), ('31.1.1.22', 0.0), ('31.1.1.9', 0.0), ('31.11.100.101', 0.0), ('31.21.18.100', 0.0), ('31.21.18.101', 0.0), ('31.21.18.221', 0.0)]

それを機能させるには、クエリ部分に何か他のものを入れる必要があると思います

どんな助けでも大歓迎です

4

1 に答える 1

3

Finally managed to do it.

The trick is to use union_all in a subquery so that it gets aliased. Then the last statement works only on that subquery

>>>top_srcs = session.query(func.inet_ntoa(IpHdr.ip_src).label('ip'),func.count('*').label('ip_count')).group_by('ip').order_by(desc('ip_count'))
>>>top_dsts = session.query(func.inet_ntoa(IpHdr.ip_dst).label('ip'),func.count('*').label('ip_count')).group_by('ip').order_by(desc('ip_count'))
>>>ts = top_srcs.subquery().select()
>>>td = top_dsts.subquery().select()
>>>q1 = session.query('ip','ip_count').select_from(union_all(ts,td).alias('mno').select()).subquery()
>>>top_total = session.query(q1.c.ip.label('ip'),func.sum(q1.c.ip_count).label('count1')).select_from(q1).group_by('ip').order_by('count1')

>>>top_total.all()
[('31.21.18.100', Decimal('924')), ('192.168.2.10', Decimal('186')), ('31.21.18.101', Decimal('171')), ('192.168.2.9', Decimal('165')), ('192.168.2.8', Decimal('96')), ('192.168.2.4', Decimal('84')), ('192.168.2.5', Decimal('78')), ('192.168.2.6', Decimal('38')), ('192.168.1.22', Decimal('31')), ('31.1.1.9', Decimal('25')), ('31.11.100.101', Decimal('17')), ('192.168.2.7', Decimal('17')), ('31.21.18.221', Decimal('6')), ('192.168.33.10', Decimal('6')), ('31.1.1.22', Decimal('4'))]
于 2012-06-27T10:42:49.963 に答える