Mysql 将SUM与多个表一起使用会产生意外的结果

Mysql 将SUM与多个表一起使用会产生意外的结果,mysql,sum,Mysql,Sum,我对数据库查询没有真正的经验,似乎找不到我要找的东西 我有一个简单的数据库,有两个表,log和block Log: +----------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+------------------+------+-----+----

我对数据库查询没有真正的经验,似乎找不到我要找的东西

我有一个简单的数据库,有两个表,log和block

Log:
+----------+------------------+------+-----+---------+----------------+
| Field    | Type             | Null | Key | Default | Extra          |
+----------+------------------+------+-----+---------+----------------+
| id       | int(11)          | NO   | PRI | NULL    | auto_increment | 
| srcip    | varchar(25)      | NO   |     | NULL    |                | 
| dstip    | varchar(25)      | NO   |     | NULL    |                | 
| cnt      | int(10) unsigned | NO   |     | NULL    |                | 
+----------+------------------+------+-----+---------+----------------+

Block: 
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| ip    | varchar(25) | YES  |     | NULL    |       | 
| shun  | int(11)     | NO   |     | NULL    |       | 
| count | int(11)     | NO   |     | 0       |       | 
+-------+-------------+------+-----+---------+-------+
我的问题是这个。运行以下查询时,sumcnt会给出意外的结果

SELECT DISTINCT srcip, SUM(cnt) as hitcnt, COUNT(DISTINCT dstip) as dstcnt
FROM  block,log
WHERE (dstip LIKE '10.10.10.%'
AND block.ip != srcip
AND srcip NOT LIKE  '$restricted'
AND time >= DATE_SUB(NOW(), INTERVAL $start_units $units)
AND time <= DATE_SUB(NOW(), INTERVAL $end_units $units))
GROUP BY srcip
ORDER BY hitcnt, INET_ATON(srcip) asc;"
如果运行相同的查询并删除日志表和引用它的语句,则每个IP地址的总和是正确的。使用这两个表的原因是,我只想显示未被阻止的IP地址。阻止的IP信息包含在阻止表中。我已经知道如何使用这两个表只显示被阻止的IP地址,但我似乎无法显示相反的IP地址

我还有几个问题需要解决,我想如果我能解决这个问题,其余的问题都会解决

任何帮助都将不胜感激。 多谢各位

更新: 这是可行的,除非总数还没有确定。其他一切看起来都很好。注:我删除了一两行代码,以保持测试的简单性

SELECT DISTINCT srcip, SUM(cnt) as hitcnt, COUNT(DISTINCT dstip) as dstcnt
FROM  log a JOIN block b
ON a.srcip != b.ip
WHERE (dstip LIKE '10.10.10.%'
AND time >= DATE_SUB(NOW(), INTERVAL 1 hour)
AND time <= DATE_SUB(NOW(), INTERVAL 0 hour)
AND srcip != ip)
GROUP BY srcip
HAVING hitcnt >= '2' AND dstcnt >= '2'
ORDER BY hitcnt, INET_ATON(srcip) ASC;
我明白了!!我知道你们会引导我走向正确的方向。谢谢大家的帮助

SELECT DISTINCT srcip, SUM(cnt) as hitcnt, COUNT(DISTINCT dstip) as dstcnt
FROM  log a LEFT JOIN block b
ON srcip = ip
WHERE (dstip LIKE '10.10.10.%' 
AND time >= DATE_SUB(NOW(), INTERVAL $start_units $units)
AND time <= DATE_SUB(NOW(), INTERVAL $end_units $units))
GROUP BY srcip
HAVING hitcnt >= '2' AND dstcnt >= '2'
ORDER BY hitcnt, INET_ATON(srcip) ASC;

正如xQbert所提到的,您可以通过FROM块log进行交叉连接,这会在块中有行的情况下,提供来自log的每一行。然后过滤掉其中的一些行,但仍有比以前更多的行

一个解决方案是子选择

SELECT DISTINCT log.srcip, 
    (SELECT SUM(cnt) FROM log WHERE log.srcip = srcip) as hitcnt, COUNT(DISTINCT dstip) as dstcnt
FROM  block,log
WHERE (dstip LIKE '10.10.10.%'
AND block.ip != srcip
AND srcip NOT LIKE  '$restricted'
AND time >= DATE_SUB(NOW(), INTERVAL $start_units $units)
AND time <= DATE_SUB(NOW(), INTERVAL $end_units $units))
GROUP BY srcip
ORDER BY hitcnt, INET_ATON(srcip) ASC
或者,您可以使用subselect创建要与之联接的第三个表:

SELECT DISTINCT log.srcip, hitcnt, COUNT(DISTINCT dstip) as dstcnt
FROM  block,log,(SELECT srcip, SUM(cnt) as hitcnt FROM log GROUP BY srcip) t
WHERE (dstip LIKE '10.10.10.%'
AND block.ip != log.srcip
AND log.srcip = t.srcip
AND log.srcip NOT LIKE  '$restricted'
AND time >= DATE_SUB(NOW(), INTERVAL $start_units $units)
AND time <= DATE_SUB(NOW(), INTERVAL $end_units $units))
GROUP BY log.srcip
ORDER BY hitcnt, INET_ATON(srcip) ASC

您的连接是交叉连接块中的所有行*日志中的所有行。这些事实上是如何相互关联的?块IP与srcIP相关,还是块IP与dstip相关?或者两者都有,或者什么?而不是将块中的这1行与日志中的这5行绑定。1行绑定到日志中的每一行。这会人为地增加计数和计数之和。日志表保存所有活动的日志。block表包含已被阻止的srcip地址。一旦它们被添加到块表中,它们就停留在那里。sun列显示它们当前是否被阻止。计数列是它们被阻止的次数。其想法是只报告当前未被阻止的SRIP。有两种方法可以显示被阻止的IP。1、用所有时间计数显示所有阻塞,2、用tact中的所有其他标志显示阻塞报告。谢谢。我两个问题都无法解决。。。然而第一个显示所有的计数相同。第二个抛出一个错误。不过没关系,这是个开始,我很感谢你的意见。我今天要摆弄一下。非常感谢。我没有时间测试它。同样的计数?你是说同一个国家?第一个查询也应该如此。secound one中的错误可能是第1、4、5和9行中的srcip不是唯一的,因此您必须使用log.srcip代替标题。我明白了,请参见顶部的“我的编辑”。没有你的帮助,我不可能做这件事。正如我所说,我只是需要一个指向正确方向的点。谢谢