2014-10-09 252 views
0

下面是我用來計算用戶的平均會話持續時間的代碼。AVG(TIMESTAMPDIFF)mySQL返回錯誤的答案

SELECT 
    tbl.create_Date 
    ,HourOfDay 
    ,HourOfDay_AMPM 

    ,AVG(TIMESTAMPDIFF(SECOND, tbl.minDt, tbl.maxDt))/60 AS Duration_mins 

    FROM (SELECT 
      i.session_id, 
      i.createDate, 
      DATE(CONVERT_TZ(i.createDate, '+00:00', '-04:00')) as create_Date, 
      HOUR(CONVERT_TZ(i.createDate, '+00:00', '-04:00')) as HourOfDay, 
      DATE_FORMAT(CONVERT_TZ(i.createDate,'+00:00','-04:00'), '%l%p') as HourOfDay_AMPM, 
      min(i.createDate) minDt, 
      max(i.createDate) maxDt, 
      (max(i.createDate) - min(i.createDate))/60 as Duration 
     FROM impressions i 

    WHERE i.createDate >= current_date 
    AND HOUR(CONVERT_TZ(i.createDate, '+00:00', '-04:00')) >=9 
    AND HOUR(CONVERT_TZ(i.createDate, '+00:00', '-04:00')) < 22 
    AND i.session_Id <> '' 


    GROUP BY i.session_id 
    HAVING Duration > 0 
    ORDER BY i.createDate, i.session_id 

     ) as tbl 
GROUP BY tbl.create_DATE, tbl.HourOfDay 

ORDER by tbl.create_Date 

注意,在數據庫中的時區是在UTC,我需要在美國東部時間來顯示結果,這就是爲什麼我用CONVERT_TZ命令。

問題:我跑的查詢和粘貼的原始數據轉換成Excel中,生成的透視表,並得到下面的結果

Hour Avg_duration_mins 
9AM  14.43 
10AM 59.17 
11AM 24.55 
12PM 12.69 
2PM  1.27 

然而,運行整個查詢作爲給我以下結果

Hour Avg_duration_mins 
9AM 6.98 
10AM 18.78 
11AM 9.40 
12PM 7.49 
2PM 1.21 

有手冊經過檢查,Excel的結果是準確的,是有道理的。爲什麼SQL變得瘋狂?我有一種感覺,問題在於AVG函數和maxmin的聚合。

更新:爲表的印象可以有相同session_id

session_id  | createDate  | actions  | 
    023awv  2014-10-09 12:02  some action 
    023awv  2014-10-09 12:12  some action 
    023awv  2014-10-09 12:22  some action 
    023awv  2014-10-09 12:32  some action 
    011awv  2014-10-09 12:42  some action 
    023awv  2014-10-09 12:42  some action 
    023awv  2014-10-09 12:52  some action 
    023awv  2014-10-09 12:53  some action 
    052brw  2014-10-09 13:02  some action 
    023awv  2014-10-09 13:05  some action 
    023awv  2014-10-09 13:06  some action 
    023awv  2014-10-09 13:08  some action 
    023awv  2014-10-09 13:12  some action 

我想在每小時/每天讓每個會話的平均持續時間的多個條目。

任何幫助將不勝感激。

+0

會議時長爲70分鐘。是否應該計入12點或13點的水平?你有這個查詢的方式是一個基本上隨機的選擇。 – Laurence 2014-10-09 22:01:28

+0

這是一個很好的觀點,我也有問題。我認爲它會選擇會話的開始時間並將其存入該插槽。 – 2014-10-09 22:05:14

+0

@Laurence:如果你能幫助我開始一個新鮮的石板,我將不勝感激。我覺得自己很困惑。如果你這樣做,你會怎麼做?我覺得'AVG'函數並沒有計算出我認爲應該達到的水平。運行內部查詢,我得到了每小時插槽的正確行數,我覺得按小時對它進行分組可以使平均值在該小時級別進行。我錯了嗎? – 2014-10-09 22:07:25

回答

0

如果您在Excel計算中使用(max(i.createDate) - min(i.createDate))/60 as Duration作爲分鐘數,那麼這是錯誤的。減去日期提供了某種間隔表示法:

select timestamp('2014-10-09 14:12') - timestamp('2014-10-09 13:04'); 

> 10800 

這是「1小時8分鐘」而不是4080秒。

您的內部查詢有一個分組,但還包括非聚合的非分組列。簡單來說:

select 
    session_id, 
    createDate -- this isn't grouped or aggregated 
from 
    impressions i 
group by 
    session_id 

大多數數據庫不會讓你這樣做。 MySQL會,它會返回第一個createDate它發生在每個session_id。所以你的內部查詢會產生不穩定的結果。單獨運行它的查詢計劃可能與用於一起運行查詢的查詢計劃不同。所以它最終會在每種情況下返回不同的值。

說出印象表包含以下兩行:

session_id | createDate 
-------------------------------- 
     1 | 2014-10-09 13:30:00 
     1 | 2014-10-09 15:30:00 

應該採取什麼內部查詢的回報?外部查詢應該返回什麼?要解決這個問題

一種方法是基於最小日期爲鬥結果:

select 
    tbl.Create_Date, 
    tbl.HourOfDay, 
    tbl.HourOfDay_AMPM, 
    avg(timestampdiff(second, tbl.minDt, tbl.maxDt))/60 as Duration_mins 
from (
    select 
     i.session_id, 
     date(convert_tz(min(i.createDate), '+00:00', '-04:00')) as create_Date, 
     hour(convert_tz(min(i.createDate), '+00:00', '-04:00')) as HourOfDay, 
     date_format(convert_tz(min(i.createDate), '+00:00', '-04:00'), '%l%p') as HourOfDay_AMPM, 
     min(i.createDate) minDt, 
     max(i.createDate) maxDt, 
     (max(i.createDate) - min(i.createDate))/60 as Duration 
    from 
     impressions i 
    where 
     i.createDate >= current_date and 
     hour(convert_tz(i.createDate, '+00:00', '-04:00')) >=9 and 
     hour(convert_tz(i.createDate, '+00:00', '-04:00')) < 22 and 
     i.session_Id <> '' 
    group by 
     i.session_id 
    having 
     Duration > 0 
    ) as tbl 
group by 
    tbl.Create_Date, 
    tbl.HourOfDay, 
    tbl.HourOfDay_AMPM 
order by 
    tbl.create_Date, 
    tbl.HourOfDay 

這裏,我已經基本上取代i.CreateDate的每一個非聚集發生在內部查詢使用分鐘( i.CreatDate)。這使得內部查詢得到了很好的定義。即只有一個結果集可以返回。

從閱讀MySQL手冊中,很難弄清楚在這種情況下,在內部查詢中執行什麼命令會起什麼作用。手冊說外部訂單將優先於內部訂單。

+0

感謝您的信息,但我很好奇,如果你可以提出修復。我是這個新手,並且仍然被你的解釋所困惑。如果你要編輯代碼,你會怎麼做? – 2014-10-09 20:12:15

+0

@ eager_learner313我在回答討論結束時提出了一個問題。 – Laurence 2014-10-09 20:15:54

+0

內部查詢每次返回相同的結果。這是外部的返回不同的結果。 內部查詢應產生以下內容 'session_id | minDt | maxDt' '1 | 2014-10-09 13:30:00 | 2014-10-09 15:30:00' – 2014-10-09 21:48:50