2013-10-21 94 views
2

之间的平均时间,所以我有数据是这样的:获取记录创建

UserID CreateDate 
1  10/20/2013 4:05 
1  10/20/2013 4:10 
1  10/21/2013 5:10 
2  10/20/2012 4:03 

我需要按每个用户得到CreateDates之间的平均时间。我想要的结果是这样的:

UserID AvgTime(minutes) 
1  753.5 
2  0 

如何找到为用户分组返回的所有记录的CreateDates之间的区别?

编辑:

使用SQL Server 2012

+1

结果应该不是'(5 + 1500)/ 2 = 752,5'? – Lamak

+0

@Lamak你是对的;我以为我用了4:10而不是5:10,谢谢。但它仍然(5 + 1500)/ 3,但该用户有三个结果平均返回501.67分钟三。 – RJP

+0

@Tonnie - 不,它应该是'753.5' - 有三个_records_但只有两个_differences_。 –

回答

7

试试这个:

SELECT A.UserID, 
     AVG(CAST(DATEDIFF(MINUTE,B.CreateDate,A.CreateDate) AS FLOAT)) AvgTime 
FROM #YourTable A 
OUTER APPLY (SELECT TOP 1 * 
      FROM #YourTable 
      WHERE UserID = A.UserID 
      AND CreateDate < A.CreateDate 
      ORDER BY CreateDate DESC) B 
GROUP BY A.UserID 
+0

这给用户2提供了NULL。这不是OP想要的。 – geomagas

+0

这个作品,谢谢!我可以将AVG语句包装在一个ISNULL中以将NULL变为0 – RJP

+0

让我们希望不可能创建两个具有相同日期和用户ID的记录 –

0

事情是这样的:

;WITH CTE AS 
(
    SELECT 
     ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY CreateDate) RN, 
     UserID, 
     CreateDate 
    FROM Tbl 
) 
SELECT 
    T1.UserID, 
    AVG(DATEDIFF(mi, ISNULL(T2.CreateDate, T1.CreateDate), T1.CreateDate)) AvgTime 
FROM CTE T1 
    LEFT JOIN CTE T2 
    ON T1.UserID = T2.UserID 
     AND T1.RN = T2.RN - 1 
GROUP BY T1.UserID 
+2

[为什么'mi'?为什么不拼写'MINUTE'?](http://sqlblog.com/blogs/aaron_bertrand/archive/2011/09/20/bad-habits-to-kick-using-shorthand-with-date-time-operations。 aspx) –

+0

@AaronBertrand区别在哪里? –

+0

@AaronBertrand我认为你必须根据[DATEDIFF(Transact-SQL)](http://msdn.microsoft.com/en-us/library/ms189794.aspx)编辑上面提到的博客帖子。 –

2

这种做法应该ASLO工作。

Fiddle demo here

;WITH CTE AS (
    Select userId, createDate, 
      row_number() over (partition by userid order by createdate) rn 
    from Table1 
) 
select t1.userid, 
     isnull(avg(datediff(second, t1.createdate, t2.createdate)*1.0/60),0) AvgTime 
from CTE t1 left join CTE t2 on t1.UserID = t2.UserID and t1.rn +1 = t2.rn 
group by t1.UserID; 

更新时间:感谢@Lemark您指出number of diff = recordCount - 1

+0

您对'UserID ='的第一个值使用值为'0' 1'。这不应该在平均值 – Lamak

+0

@Lamak上考虑; [检查这个](http://sqlfiddle.com/#!6/84ba5/4),第二个是你的查询,它不给这些值。有点混淆的价值观。 – Kaf

+0

因为op在他的计算上是错误的,我的观点是正确的:http://stackoverflow.com/questions/19501789/get-average-time-between-record-creation?noredirect=1#comment28928501_19501789 – Lamak

0

随着SQL 2012可以使用ROW_NUMBER功能和自联接查找 “前”每组中的排:

WITH Base AS 
(
SELECT 
    ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY CreateDate) RowNum, 
    UserId, 
    CreateDate 
FROM Users 
) 
SELECT 
    B1.UserID, 
    ISNULL(
     AVG(
      DATEDIFF(mi,B2.CreateDate,B1.CreateDate) * 1.0 
     ) 
    ,0) [Average] 
FROM Base B1 
LEFT JOIN Base B2 
    ON B1.UserID = B2.UserID 
    AND B1.RowNum = B2.RowNum + 1 
GROUP BY B1.UserId 

虽然我获得用户ID 1不同的答案 - 我得到的,因为你正在使用的2012(5 + 1500)/ 2 = 752

+0

[为什么'mi'?为什么不拼写'MINUTE'?](http://sqlblog.com/blogs/aaron_bertrand/archive/2011/09/20/bad-habits-to-kick-using-shorthand-with-date-time-operations。 ASPX) –

2

平均可使用铅()来做到这一点

with cte as 
(select 

     userid, 
     (datediff(second, createdate, 
        lead(CreateDate) over (Partition by userid order by createdate) 
        )/60) datdiff 


From table1 
) 
select 
    userid, 
    avg(datdiff) 
from cte 
group by userid 

Demo

0

在2012年这仅适用于您可以使用LEAD解析函数:

CREATE TABLE dates (
    id integer, 
    created datetime not null 
); 

INSERT INTO dates (id, created) 
SELECT 1 AS id, '10/20/2013 4:05' AS created 
UNION ALL SELECT 1, '10/20/2013 4:10' 
UNION ALL SELECT 1, '10/21/2013 5:10' 
UNION ALL SELECT 2, '10/20/2012 4:03'; 

SELECT id, isnull(avg(diff), 0) 
FROM (
    SELECT id, 
    datediff(MINUTE, 
      created, 
      LEAD(created, 1, NULL) OVER(partition BY id ORDER BY created) 
      ) AS diff 
    FROM dates 
) as diffs 
GROUP BY id; 

http://sqlfiddle.com/#!6/4ce89/22

相关问题