按组划分的同一字段中日期之间的平均时间
Average time between dates in same field by groups
我有一个包含销售数据和用户 ID 的交易数据库,如下所示:
id_usuarioweb dt_fechaventa
1551415 2015-08-01 14:57:21.737
1551415 2015-08-06 15:34:21.920
6958538 2015-07-30 09:26:24.427
6958538 2015-08-05 09:30:06.247
6958538 2015-08-31 17:39:02.027
39101175 2015-08-05 16:34:17.990
39101175 2015-09-20 20:37:26.043
1551415 2015-09-05 13:41:43.767
3673384 2015-09-06 13:34:23.440
并且我想计算数据库中同一客户的日期之间的平均差异(以找出用户购买的平均频率)。
我知道我可以对两列进行 datediff,但我在尝试在同一字段中并 "grouping" 按用户 ID 进行操作时遇到问题。
期望的结果是这样的:
id_usuarioweb avgtime_days
1551415 5
6958538 25
39101175 25
1551415 0
3673384 0
我怎样才能做到这一点?我会让数据库按 user_id 排序,然后按 dt_fechaventa(销售时间)排序。
使用:SQL服务器 2008
我想你要找的是这样计算的。取最大和最小日期,得到它们之间的差值并除以购买数量。
SELECT id_usuarioweb, CASE
WHEN COUNT(*) < 2
THEN 0
ELSE DATEDIFF(dd,
MIN(
dt_fechaventa
), MAX(
dt_fechaventa
)) / (
COUNT(*) -
1
)
END AS avgtime_days
FROM mytable
GROUP BY id_usuarioweb
编辑:(@GordonLinoff)
如果你看一下数学就很容易看出这是正确的原因。考虑三个日期 a、b 和 c。
他们之间的平均时间是:
((b - a) + (c - b)) / 2
这简化为:
(c - a) / 2
换句话说,中间值抵消了。而且,无论中间值的数量如何,这种情况都会继续。
您可以先使用 row_number
对行进行编号,然后使用 cte
进行 self-join
。然后执行average
。但是,您会为每个用户获得一行,但不是预期的结果。
with x as
(select id_usuarioweb, dt_fechaventa,
row_number() over(partition by id_usuarioweb order by dt_fechaventa) as rn
from tablename)
select x1.id_usuarioweb, avg(datediff(dd,x1.dt_fechaventa,x2.dt_fechaventa)) as avgdiff
from x x1 join x x2
on x1.id_usuarioweb = x2.id_usuarioweb and x1.rn = x2.rn-1
group by x1.id_usuarioweb
应该这样做:
;WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY id_usuarioweb ORDER BY dt_fechaventa),
N = COUNT(*) OVER(PARTITION BY id_usuarioweb)
FROM dbo.YourTable
)
SELECT A.id_usuarioweb,
AVG(DATEDIFF(DAY,A.dt_fechaventa,B.dt_fechaventa)) avgtime_days
FROM CTE A
INNER JOIN CTE B
ON A.id_usuarioweb = B.id_usuarioweb
AND A.RN = B.RN - 1
WHERE A.N > 1
GROUP BY A.id_usuarioweb;
我正在过滤那里只有一行的用户,因为你无法计算与他们在一起的平均天数。
Here is a demo 在这个的sqlfiddle中。结果是:
╔═══════════════╦══════════════╗
║ id_usuarioweb ║ avgtime_days ║
╠═══════════════╬══════════════╣
║ 1551415 ║ 17 ║
║ 6958538 ║ 16 ║
║ 39101175 ║ 46 ║
╚═══════════════╩══════════════╝
我有一个包含销售数据和用户 ID 的交易数据库,如下所示:
id_usuarioweb dt_fechaventa
1551415 2015-08-01 14:57:21.737
1551415 2015-08-06 15:34:21.920
6958538 2015-07-30 09:26:24.427
6958538 2015-08-05 09:30:06.247
6958538 2015-08-31 17:39:02.027
39101175 2015-08-05 16:34:17.990
39101175 2015-09-20 20:37:26.043
1551415 2015-09-05 13:41:43.767
3673384 2015-09-06 13:34:23.440
并且我想计算数据库中同一客户的日期之间的平均差异(以找出用户购买的平均频率)。
我知道我可以对两列进行 datediff,但我在尝试在同一字段中并 "grouping" 按用户 ID 进行操作时遇到问题。
期望的结果是这样的:
id_usuarioweb avgtime_days
1551415 5
6958538 25
39101175 25
1551415 0
3673384 0
我怎样才能做到这一点?我会让数据库按 user_id 排序,然后按 dt_fechaventa(销售时间)排序。
使用:SQL服务器 2008
我想你要找的是这样计算的。取最大和最小日期,得到它们之间的差值并除以购买数量。
SELECT id_usuarioweb, CASE
WHEN COUNT(*) < 2
THEN 0
ELSE DATEDIFF(dd,
MIN(
dt_fechaventa
), MAX(
dt_fechaventa
)) / (
COUNT(*) -
1
)
END AS avgtime_days
FROM mytable
GROUP BY id_usuarioweb
编辑:(@GordonLinoff)
如果你看一下数学就很容易看出这是正确的原因。考虑三个日期 a、b 和 c。
他们之间的平均时间是:
((b - a) + (c - b)) / 2
这简化为:
(c - a) / 2
换句话说,中间值抵消了。而且,无论中间值的数量如何,这种情况都会继续。
您可以先使用 row_number
对行进行编号,然后使用 cte
进行 self-join
。然后执行average
。但是,您会为每个用户获得一行,但不是预期的结果。
with x as
(select id_usuarioweb, dt_fechaventa,
row_number() over(partition by id_usuarioweb order by dt_fechaventa) as rn
from tablename)
select x1.id_usuarioweb, avg(datediff(dd,x1.dt_fechaventa,x2.dt_fechaventa)) as avgdiff
from x x1 join x x2
on x1.id_usuarioweb = x2.id_usuarioweb and x1.rn = x2.rn-1
group by x1.id_usuarioweb
应该这样做:
;WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY id_usuarioweb ORDER BY dt_fechaventa),
N = COUNT(*) OVER(PARTITION BY id_usuarioweb)
FROM dbo.YourTable
)
SELECT A.id_usuarioweb,
AVG(DATEDIFF(DAY,A.dt_fechaventa,B.dt_fechaventa)) avgtime_days
FROM CTE A
INNER JOIN CTE B
ON A.id_usuarioweb = B.id_usuarioweb
AND A.RN = B.RN - 1
WHERE A.N > 1
GROUP BY A.id_usuarioweb;
我正在过滤那里只有一行的用户,因为你无法计算与他们在一起的平均天数。
Here is a demo 在这个的sqlfiddle中。结果是:
╔═══════════════╦══════════════╗
║ id_usuarioweb ║ avgtime_days ║
╠═══════════════╬══════════════╣
║ 1551415 ║ 17 ║
║ 6958538 ║ 16 ║
║ 39101175 ║ 46 ║
╚═══════════════╩══════════════╝