2013-10-21 120 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

相關問題