有一个包含访问数据的表:
uid (INT) | created_at (DATETIME)
我想查找用户连续几天访问了我们的应用程序。因此,例如:
SELECT DISTINCT DATE(created_at) AS d FROM visits WHERE uid = 123
将返回:
d
------------
2012-04-28
2012-04-29
2012-04-30
2012-05-03
2012-05-04
有5条记录和两个间隔-3天(4月28日至30日)和2天(5月3日至4日)。
我的问题是如何找到用户连续访问该应用程序的最大天数(在示例中为3天)。试图在SQL文档中找到合适的函数,但没有成功。我想念什么吗?
UPD:
谢谢您的回答!实际上,我正在使用vertica分析数据库(http://vertica.com/),但这是一种非常罕见的解决方案,只有很少的人有使用它的经验。尽管它支持SQL-99标准。
好吧,大多数解决方案都需要稍作修改。最后,我创建了自己的查询版本:
-- returns starts of the vitit series
SELECT t1.d as s FROM testing t1
LEFT JOIN testing t2 ON DATE(t2.d) = DATE(TIMESTAMPADD('day', -1, t1.d))
WHERE t2.d is null GROUP BY t1.d
s
---------------------
2012-04-28 01:00:00
2012-05-03 01:00:00
-- returns end of the vitit series
SELECT t1.d as f FROM testing t1
LEFT JOIN testing t2 ON DATE(t2.d) = DATE(TIMESTAMPADD('day', 1, t1.d))
WHERE t2.d is null GROUP BY t1.d
f
---------------------
2012-04-30 01:00:00
2012-05-04 01:00:00
因此,现在我们唯一需要做的就是以某种方式将它们连接起来,例如通过行索引。
SELECT s, f, DATEDIFF(day, s, f) + 1 as seq FROM (
SELECT t1.d as s, ROW_NUMBER() OVER () as o1 FROM testing t1
LEFT JOIN testing t2 ON DATE(t2.d) = DATE(TIMESTAMPADD('day', -1, t1.d))
WHERE t2.d is null GROUP BY t1.d
) tbl1 LEFT JOIN (
SELECT t1.d as f, ROW_NUMBER() OVER () as o2 FROM testing t1
LEFT JOIN testing t2 ON DATE(t2.d) = DATE(TIMESTAMPADD('day', 1, t1.d))
WHERE t2.d is null GROUP BY t1.d
) tbl2 ON o1 = o2
样本输出:
s | f | seq
---------------------+---------------------+-----
2012-04-28 01:00:00 | 2012-04-30 01:00:00 | 3
2012-05-03 01:00:00 | 2012-05-04 01:00:00 | 2
最短的另一种方法是进行自我联接:
with grouped_result as
(
select
sr.d,
sum((fr.d is null)::int) over(order by sr.d) as group_number
from tbl sr
left join tbl fr on sr.d = fr.d + interval '1 day'
)
select d, group_number, count(d) over m as consecutive_days
from grouped_result
window m as (partition by group_number)
输出:
d | group_number | consecutive_days
---------------------+--------------+------------------
2012-04-28 08:00:00 | 1 | 3
2012-04-29 08:00:00 | 1 | 3
2012-04-30 08:00:00 | 1 | 3
2012-05-03 08:00:00 | 2 | 2
2012-05-04 08:00:00 | 2 | 2
(5 rows)
实时测试:http://www.sqlfiddle.com/#!1/93789/1
SR =第二行,FR
=第一行(或者前一行?銉)。基本上,我们正在执行向后跟踪,这是数据库不支持的模拟滞后LAG
(Postgres支持LAG,但解决方案很长,因为窗口不支持嵌套窗口)。因此,在此查询中,我们使用混合方法,通过联接模拟LAG,然后对其使用SUM窗口化,从而产生组号
更新
忘记了最终查询,上面的查询说明了组编号的基础,需要将其变形为:
with grouped_result as
(
select
sr.d,
sum((fr.d is null)::int) over(order by sr.d) as group_number
from tbl sr
left join tbl fr on sr.d = fr.d + interval '1 day'
)
select min(d) as starting_date, max(d) as end_date, count(d) as consecutive_days
from grouped_result
group by group_number
-- order by consecutive_days desc limit 1
STARTING_DATE END_DATE CONSECUTIVE_DAYS
April, 28 2012 08:00:00-0700 April, 30 2012 08:00:00-0700 3
May, 03 2012 08:00:00-0700 May, 04 2012 08:00:00-0700 2
更新
我知道为什么我的其他使用窗口函数的解决方案变长了,为什么我试图说明组编号和对组进行计数的逻辑又变长了。如果我像MySql方法那样追求目标,那么该窗口函数可能会更短。话虽如此,这是我以前的窗口函数方法,尽管现在更好:
with headers as
(
select
d,lag(d) over m is null or d - lag(d) over m <> interval '1 day' as header
from tbl
window m as (order by d)
)
,sequence_group as
(
select d, sum(header::int) over (order by d) as group_number
from headers
)
select min(d) as starting_date,max(d) as ending_date,count(d) as consecutive_days
from sequence_group
group by group_number
-- order by consecutive_days desc limit 1
实时测试:http://www.sqlfiddle.com/#!1/93789/21
问题内容: 我希望为每个人计算连续的一天咒语。 我的表: 这是我目前拥有的代码: 产生结果: 在我正在寻找这样的结果集的地方: 我需要计算连续1天以上的连续天数。然后将其作为某人拥有多少个连续咒语的总和。例如,弗雷德在这段时间内连续2次生病。如果某人有星期五和星期一休息,我也需要此内容,这应该算作一个连续的咒语。 我对如何到达那里有些迷失。任何帮助将不胜感激。 请参阅:http ://sqlfid
问题内容: 我的表格“订单”中有50行/条目。我有一列名为的列,该列用于保存在处的订单声明。 此字段中的日期格式如下:2011-10-03 07:07:33 格式为(yy / mm / dd time)。 我也有一个专栏,这是他们支付的金额。 我想显示每天的总数。 因此,对于2011年10月3日之后的6个订单,应采用6个订单的值,并将它们加在一起。 所以我可以显示: 我怎样才能做到这一点? 问题答
问题内容: 如果我有这样的表和数据: 我希望按照从小到大的Group总数对它进行排序,例如:A-2个记录,B-1个记录,C-3个记录,因此它将变为: 我试过了 但这只会为我返回一个结果。 有什么提示吗?谢谢。 问题答案: 您需要首先聚合数据,这可以使用GROUP BY子句完成: 关键字DESC允许您首先显示最高计数,默认情况下按ORDER BY升序排列,这将首先显示最低计数。
我有两个表用于存储员工出勤信息。 一个表存储emp Id以及相应的时间和日期时间信息。第二个表存储其他员工详细信息,如员工Id、员工姓名等。。。我需要生成一份报告,显示emp每天工作的总小时数,一个状态列存储详细信息,如Present if total hours 我写了查询来获取每一个细节,但性能是不可接受的,需要大约30-35分钟来获取所有细节 如果排除天数计算逻辑,大约需要1-2分钟 表的结
问题内容: 我正在寻找一种方法来计算等于组的最小或最大项目数。我每隔几天收到一次商品,每两周输入一次。我需要查看每个EntryDate的最小值和最大值ReceivedDate,以及最小值和最大值处的项目计数。在MS Access中使用SQL。 输入 当前查询 电流输出 期望的输出 问题答案: 我不知道MS Access是否允许这样的子查询。如果这不起作用,请让我知道,我将删除答案。否则:
我需要帮助写一些代码,计算最大可能的胜利在N游戏的岩石剪刀纸。 给我的是数字N,这是岩石纸剪刀游戏的数量,后面是N组整数(1,2,3),每个都链接到岩石,纸或剪刀。但是,我们不知道哪个数字链接到每个选项。我需要帮助计算第一个人可以赢的最多游戏数。