1

考虑以下简单的 MySQL 查询:

SELECT date, count(*) cnt, ip 
FROM fwlog
GROUP BY ip, date
HAVING cnt>100
ORDER BY date DESC, cnt DESC

它给了我类似的东西:

date    cnt     src
2013-06-20      14441   172.16.a
2013-06-20      8887    172.16.b
....
2013-06-19      14606   172.16.b
2013-06-19      12455   172.16.a
2013-06-19      5205    172.16.c

也就是说,它按日期对 IP 进行排序,然后按照指示对 IP 进行排序。

现在我希望结果是:

  • 首先显示TODAY计数最高的IP,
  • 然后显示过去几天该 IP 的计数(独立于 cnt),
  • 然后显示 TODAY 计数第二高的 IP,
  • 然后是那个IP的历史,
  • 等。

期望结果的示例:

date    cnt     src
2013-06-20      14441   172.16.a
2013-06-19      12455   172.16.a
2013-06-18      ....    172.16.a
2013-06-17      ....    172.16.a
....
2013-06-20      8887    172.16.b
2013-06-19      14606   172.16.b
2013-06-18      ....    172.16.b
2013-06-17      ....    172.16.b
...
2013-06-20      ....    172.16.c
2013-06-19      ....    172.16.c
2013-06-18      ....    172.16.c
2013-06-17      ....    172.16.c
...
...

这甚至可以使用纯 SQL 来完成吗?

再见,

马基

===========================================

@戈登林诺夫:

SELECT 
    datex,
    cnt,
    ip
FROM
    fwlog
WHERE
    ...
GROUP BY ip , datex
ORDER BY SUM(case
    when datex = DATE(NOW()) then 1
    else 0
end) DESC , src, date DESC, cnt DESC

2013-06-20      47      10.11.y
2013-06-19      47      10.11.y
2013-06-18      45      10.11.y
2013-06-17      42      10.11.y
2013-06-16      14      10.11.y
....
2013-06-20      592     172.16.a
2013-06-19      910     172.16.a
2013-06-18      594     172.16.a
2013-06-17      586     172.16.a
2013-06-20      299     172.16.b

这还不完全正确,较低的块应该在顶部。

4

3 回答 3

1

您需要在order by子句中添加当前日期的计数。获取当前日期因数据库而异。这是 SQL Server 的版本:

SELECT date, count(*) cnt, ip 
FROM fwlog
GROUP BY ip, date
HAVING cnt > 100
ORDER BY SUM(case when date = cast(GETDATE() as date) then 1 else 0 end) desc,
         ip,
         date DESC, cnt DESC

ip当两个具有相同的当前计数时,排序会处理这种情况。

其他数据库可能使用now()、sysdate()`、CURRENT_TIMESTAMP 或类似的东西或当前日期。

于 2013-06-21T15:32:23.353 回答
1

尝试:

SELECT a.`date`, count(*) cnt, a.ip 
FROM fwlog a
JOIN (SELECT ip, count(*) today_count
      FROM fwlog 
      where `date` = date(now()) 
      group by ip) t
  ON a.ip = t.ip and t.today_count > 100
GROUP BY a.ip, a.date
ORDER BY t.today_count DESC, a.ip, a.`date` DESC
于 2013-06-21T15:55:28.920 回答
0

以下似乎有效。谢谢。

SELECT 
    str_to_date(a.date, _utf8'%e%b%Y') datex,
    count(*) cnt,
    a.src
FROM
    fwlog a
        JOIN
    (SELECT 
        src, count(*) latest_count
    FROM
        fwlog
    WHERE
        str_to_date(fwlog.date, '%e%b%Y') = subdate(current_date, 1)
            AND ((fwlog.action <> 'accept')
            AND (fwlog.message_info <> 'Implied rule')
            AND (fwlog.proto NOT IN ('icmp' , 'igmp')))
    GROUP BY src) b ON a.src = b.src AND b.latest_count > 10
WHERE
    ((a.action <> 'accept')
        AND (a.message_info <> 'Implied rule')
        AND (a.proto NOT IN ('icmp' , 'igmp')))
GROUP BY a.src , datex
ORDER BY b.latest_count DESC , a.src , datex DESC
  • 使用 str_to_date 是因为格式最初不是真正的日期类型
  • 有一些 WHERE 条件,您必须注意它们存在于内部和外部查询中
  • 使用 subdate 是因为 latest_count 来自昨天(但这是一个细节,它也适用于今天)

最后你会得到一个很好的结果,如下所示:

'2013-06-20', '14441', '172.16.a'
'2013-06-19', '14606', '172.16.a'
'2013-06-18', '14338', '172.16.a'
'2013-06-17', '7665', '172.16.a'
'2013-06-20', '8887', '172.16.b'
'2013-06-19', '12455', '172.16.b'
'2013-06-18', '10040', '172.16.b'
'2013-06-20', '5744', '172.16.c'
....

我接受马克班尼斯特的回答,因为它最接近有效。

于 2013-06-21T17:31:22.550 回答