我对数据库查询并不熟悉,似乎找不到我想要的东西。
我有一个简单的数据库,包含2个表,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 | |
+-------+-------------+------+-----+---------+-------+
我的问题是这个。运行以下查询时,sum(cnt)会产生意外结果。
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地址,但显示反向似乎是在逃避我。
我还有一些要构建的查询,我想如果我可以让这个人工作,其余的应该落实到位。
任何帮助将不胜感激。 谢谢。
更新: 除了SUM仍然关闭之外,这个工作正常。其他一切看起来都不错。注意我删除了一两行,以便于测试。
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;
答案 0 :(得分:0)
正如xQbert所提到的那样,你通过FROM block, log
进行交叉联接,它为log
中的每一行提供block
中的行。然后你把它们中的一些过滤掉了,但是你仍然有比以前更多的行。
解决方案将是一个子选择。
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
或者您可以使用子选择创建要加入的第三个表:
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