2010-08-19 71 views
1

給出以下表格,我將如何去查找所有表中最常見的IP地址,並且理想情況下,在所有表中發生ip的次數。在多個表中找到最常見的值

bad_guys_1   bad_guys_2 
| id | ip  | | id | ip  | 
+----+---------+ +----+---------+ 
| 1 | 1.2.3.4 | | 1 | 1.2.3.4 | 
| 2 | 2.3.4.5 | | 2 | 4.5.6.7 | 
| 3 | 3.4.5.6 | | 3 | 1.2.3.4 | 

bad_guys_3   bad_guys_4 
| id | ip  | | id | ip  | 
+----+---------+ +----+---------+ 
| 1 | 9.8.7.6 | | 1 | 1.2.3.4 | 
| 2 | 8.7.6.5 | | 2 | 2.3.4.5 | 
| 3 | 2.3.4.5 | | 3 | 3.4.5.6 | 

例如,查詢上述表應導致類似:

| ip  | count | 
+---------+-------+ 
| 1.2.3.4 | 4  | 
| 2.3.4.5 | 3  | 
| 3.4.5.6 | 2  | 
| 4.5.6.7 | 1  | 
| 9.8.7.6 | 1  | 
| 8.7.6.5 | 1  | 

真正的表格實際上含有不彼此,從而單獨的表排隊許多附加字段。我並不在乎打破比賽之間的關係,只要按照降序排列他們就會很好。我的數據庫是PostGreSQL,如果使用任何非標準函數都會有所幫助,但是爲了可移植性,如果可能的話,更喜歡使用標準sql。謝謝,讓我知道你是否需要更多的細節。

+0

哇,那很快!你們真棒。感謝大家。 – Andy 2010-08-19 14:17:15

回答

6

遺憾地說,但對方的回答只用union,而不是union all是錯誤的。如果選定的行出現在多個表中,則只有在通過聯合包含其他表時纔會將其計入第一個表中,而不是全部聯合。

對於那些同時選擇ID和地址的查詢,在不同表中存在具有相同ID和地址的行的可能性仍然存在。使用UNION ALL可確保所有值都是聯合的,不管它們是否重複 - 我們都希望重複項能夠被計數。使用UNION ALL對於數據庫來說往往工作較少,因爲它不需要查找重複項並將其刪除。

select ip, count(*) from 
(
select ip from bad_guys_1 
union ALL 
select ip from bad_guys_2 
union ALL 
select ip from bad_guys_3 
union ALL 
select ip from bad_guys_4 
) as ranking 
group by ip 
order by count(*) DESC 
+0

是的,你說得對。使用union來運行它會給我每個結果計數1,但union all顯示了每個給定ip在所有表中顯示的正確總次數。 – Andy 2010-08-19 14:25:44

1

嘗試......

select ip, count(*) 
from 
(
select id, ip from bad_guys_1 
union all 
select id, ip from bad_guys_2 
union all 
select id, ip from bad_guys_3 
union all 
select id, ip from bad_guys_4 
) a 
group by ip 
order by count(*) desc 
+1

你需要UNION ALL而不是UNION,或者在2,3中重複值,並且4個表不會被計數。 – mdma 2010-08-19 14:12:23

+0

已更新..雖然ID和IP匹配的可能性很小,但您是正確的。 – Fosco 2010-08-19 14:20:02

1

安迪, 您可以使用「聯盟」,創建一個大的邏輯表(在內存中)只用IP地址。然後,你可以做正常的

select count(ip), ip from 
(select ip from table1 union all select ip from table2 etc) unionedTable 
group by ip 

[編輯追加UNION ALL - !感謝]

+2

您需要UNION ALL而不是UNION,否則不會計算不同表中的重複值。 – mdma 2010-08-19 14:11:24

+0

固定。感謝mdma。 – 2010-08-19 15:30:56

1
 select ip, count(*) from 
     (
     select id, ip from bad_guys_1 
     union all 
     select id, ip from bad_guys_2 
     union all 
     select id, ip from bad_guys_3 
     union all 
     select id, ip from bad_guys_4 
     ) as ranking 
     group by ip 

order by count(*) desc 
+1

您需要UNION ALL而不是UNION,或2,3中重複的值,並且4個表格不會被計算在內。 (假設他們也有相同的ID,這是可能的。) – mdma 2010-08-19 14:11:52

2
SELECT ip, count(*) c 
FROM 
(
    SELECT ip 
    from bad_guys_1 
    UNION ALL 
    SELECT ip 
    from bad_guys_2 
    UNION ALL 
    SELECT ip 
    from bad_guys_3 
    UNION ALL 
    SELECT ip 
    from bad_guys_4) 
group by ip 
order by 2 desc