按组划分的同一字段中日期之间的平均时间

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 ║
╚═══════════════╩══════════════╝