Mysql 在一个时间段内查找最大项目的算法建议

Mysql 在一个时间段内查找最大项目的算法建议,mysql,sql,Mysql,Sql,我有一个类似于以下内容的数据库架构: | User | Event | Date |--------|---------------|------ | 111 | Walked dog | 2009-10-1 | 222 | Walked dog | 2009-10-2 | 333 | Fed Fish | 2009-10-5 | 222 | Did Laundry | 2009-10-6 | 111 | Fed Fis

我有一个类似于以下内容的数据库架构:

| User   | Event         | Date
|--------|---------------|------
| 111    | Walked dog    | 2009-10-1
| 222    | Walked dog    | 2009-10-2
| 333    | Fed Fish      | 2009-10-5
| 222    | Did Laundry   | 2009-10-6
| 111    | Fed Fish      | 2009-10-7
| 111    | Walked dog    | 2009-10-18
| 222    | Walked dog    | 2009-10-19
| 111    | Fed Fish      | 2009-10-21
我想生成一个查询,返回用户在一个时间段内执行某些操作的最大次数。例如,给定5天的时间段,用户111遛狗的最大次数是多少

最明显的解决方案是从某个零点开始,每天向前移动,将沿途的5天时间相加,然后从所有5天窗口中取最大值。然而,这种方法似乎成本极高

如果您有任何建议,我将不胜感激

编辑1:

谢谢你的评论/回答。答复: -我正在使用mySQL v5.0 -实际上,在任何时间段,每天都可能发生任何数量的事件 -@Paulo Santos:谢谢,但正如评论所指出的,我需要找到产生最多结果的窗口,窗口本身可以滑动。 -@Mark:这看起来是一个有趣的解决方案,尽管我记得读到mySQL不支持备份或跳转游标。 -@orbMan:这看起来很有希望。我还不完全明白,但今晚我会试试。 -@mjv:另一个有希望的解决方案。看起来也很复杂,但我会再看一眼

再次感谢

对于您的具体要求,我会采取如下措施:

SELECT User, Event, Count(*)
  FROM Table
 WHERE Date between @d1 and @d2
 Group by User, Event

然后,它将返回每个用户在指定的@d1和@d2时间范围内执行每个任务的时间数。

这里有一个基于光标的替代算法

从两个光标开始,开始和结束,都指向初始行,当前计数=0,当前最大值=0

如果DATE\u DIFFend.DATE、begin.DATE大于5,则将开始光标向前移动一行。如果旧行为“遛狗”,则从当前计数中减去一

如果DATE\u DIFFend.DATE、begin.DATE不超过5,则将结束光标向前移动一行。A如果新行为“遛狗”,则将一个添加到当前计数。如果当前计数大于当前最大值,请将当前最大值设置为当前计数


继续,直到覆盖了该范围内的所有行。

以下SQL代码以声明方式而不是纯粹的过程/算法方式解决问题。根据具体情况,它可能比从SQL获取[排序]数据然后运行某些算法更有效,甚至比服务器端基于游标的解决方案更有效

其思想是在单独的表或CTE中获得每个用户每天的[相关/过滤]事件计数。然后,对于每天+用户,统计这一天和接下来4天的事件数量,最后选择每个用户行中最大的事件数量

SELECT User, Date, COUNT(*) AS EventCount
INTO tmpTableByUsrByDay
FROM myTable
-- WHERE Event = some_targeted_event   --Optional condition(s)
GROUP BY User, Date, COUNT(*)


SELECT DISTINCT User, Date AS FirstDay, 
   MAX(FiveFaysEventCount) AS EventCountForThisAndNext4Days.
FROM (
  SELECT T1.User, T1.Date, SUM(T2.EventCount) FiveDaysEventCount
  FROM tmpTableByUsrByDay T1
  JOIN tmpTableByUsrByDay T2 ON T2.Date >= T1.Date 
       AND T2.Date <= DATEADD(day, 4, T1.Date)
  GROUP BY T1.User, T1.Date
)
注: -它使用一个临时表,尽管根据底层SQL主机的不同,可以使用公共表表达式CTE。 -DateAdd函数的特定名称/语法可能因SQL实现而异。 -这也意味着date字段只包含一个日期,即日期或datetime/smalldatetime,其中时间部分固定为00:00。如果情况并非如此,即如果数据库在列中有日期和时间,则可以在CTE/temp表查询级别修复此问题

select top 1 x.Date as StartDate, DATEADD(day, 5, x.Date) as EndDate, COUNT(*) as Count
from Event e
inner join Event x on 1=1
where e.Date between x.Date and DATEADD(day, 5, x.Date)
    and e.Event = 'Walked dog'
group by x.Date, DATEADD(day, 5, x.Date)
order by Count desc
输出:


您使用的是支持SQL的DBMS还是没有查询语言的平面文件源之类的?每天只能有零个或一个事件吗?我认为Darren并不是这么问的。相反,他希望找出用户最常执行任务的五天时间。他在问是否有一种方法可以确定这一点,而不必在连续的五天内执行一次查询。我会研究一下。。。这不是小事,但也不是那么难。更新了一个更宽松的版本,从任何事件日开始计算天数。
StartDate  EndDate    Count
---------- ---------- -----------
2009-10-01 2009-10-06 2