在多个表中查找最常见的值

时间:2010-08-19 14:03:46

标签: sql postgresql

给出下面的表格,我将如何在所有表中找到最常见的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。谢谢,如果您需要更多细节,请告诉我。

5 个答案:

答案 0 :(得分:6)

很抱歉,但仅使用union而非union all的其他答案是错误的。如果有一个选定的行出现在多个表中,那么只有在通过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

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分:1)

安迪 您可以使用“联合”来仅使用IP创建一个大的逻辑表(在内存中)。然后你可以做正常的

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

[编辑添加联盟 - 谢谢!]

答案 4 :(得分: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