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