2016-08-28 47 views
0

我試圖計算最後X天的每個日期的conversations的中位數response time按列分組但是每個都得到多個結果

我使用下面的查詢,但由於某種原因,它會生成多個具有相同日期的行。

with grouping as (
     SELECT a.id, d.date, extract(epoch from (first_response_at - started_at)) as response_time 
     FROM (
      select to_char(date_trunc('day', (current_date - offs)), 'YYYY-MM-DD') AS date 
      FROM generate_series(0, 2) AS offs 
     ) d 
     LEFT OUTER JOIN apps a on true 
     LEFT OUTER JOIN conversations c ON (d.date=to_char(date_trunc('day'::varchar, c.started_at), 'YYYY-MM-DD')) and a.id = c.app_id 
     and c.app_id = a.id and c.first_response_at > (current_date - (2 || ' days')::interval)::date 
    ) 
     select 
     * 
     from grouping 
     where grouping.id = 'ASnYW1-RgCl0I' 

任何想法?

+0

您是否嘗試過使用DISTINCT? –

+0

這不會解決它,因爲我不知道重複行中的哪一個(如果有)具有正確的中位響應時間 – Tarlen

+1

您正在通過左側加入true來執行帶'apps'的'CROSS JOIN'。如果您希望我們進一步調查,請附上sqlfiddle或腳本以生成樣本數據和預期結果 –

回答

2

首先許多與您的查詢問題,假設有沒有你還沒有告訴我們任何部件:您不需要CTE此查詢

  • 從表apps您只能使用id列,其值與c.app_id相同。您可以刪除表apps並選擇c.app_id獲得相同的結果。
  • 當您使用to_char()時,您不必首先將date_trunc()設置爲dateto_char()函數可以處理該問題。
  • generate_series()也適用於timestamps。只需輸入一個時間間隔的日期值,並在使用前將結果轉換爲date即可。

所以,清除所有我們結束了這個這不完全一樣,你的問題查詢,但現在我們至少可以看到正在發生的事情的廢料。

SELECT c.app_id, to_date(d.date, 'YYYY-MM-DD') AS date, 
     extract(epoch from (first_response_at - started_at)) AS response_time 
FROM generate_series(CURRENT_DATE - 2, CURRENT_DATE, interval '1 day') d(date) 
LEFT JOIN conversations c ON d.date::date = c.started_at::date 
         AND c.app_id = 'ASnYW1-RgCl0I' 
         AND c.first_response_at > CURRENT_DATE - 2;

您不計算任何地方的中位響應時間,所以這是一個需要解決的大問題。這隻需要從表conversations數據看起來有點像這樣來計算,在過去2天中位數響應時間:

SELECT app_id, started_at::date AS start_date, 
     percentile_disc(0.5) WITHIN GROUP (ORDER BY first_response_at - started_at) AS median_response 
FROM conversations 
WHERE app_id = 'ASnYW1-RgCl0I' 
    AND first_response_at > CURRENT_DATE - 2 
GROUP BY 2; 

當我們折了兩個查詢,並把參數輕而易舉地在一個地方,這是最終的結果:

SELECT p.id, to_date(d.date, 'YYYY-MM-DD') AS date, 
     extract(epoch from (c.median_response)) AS response_time 
FROM (VALUES ('ASnYW1-RgCl0I', 2)) p(id, days) 
JOIN generate_series(CURRENT_DATE - p.days, CURRENT_DATE, interval '1 day') d(date) ON true 
LEFT JOIN LATERAL (
    SELECT started_at::date AS start_date, 
      percentile_disc(0.5) WITHIN GROUP (ORDER BY first_response_at - started_at) AS median_response 
    FROM conversations 
    WHERE app_id = p.id 
     AND first_response_at > CURRENT_DATE - p.days 
    GROUP BY 2) c ON d.date::date = c.start_date;

如果要更改應用程序或天數的id回頭看看,你只需要相應地改變VALUES條款。您也可以將整個事件包裝在SQL函數中,並將VALUES子句轉換爲兩個參數。

+0

這很棒,幾乎完美。問題是,如果沒有日期結果,app_id爲空,當稍後嘗試將其聚合到數組時,這是個問題。 – Tarlen

+0

然後,不是選擇'c.app_id',而是將字符串'ASnYW1-RgCl0I' ,因爲你無論如何都不會在查詢中修改它。答案已更新。 – Patrick

+0

我寧願不對硬件代碼進行硬編碼,因爲這個想法是將所有應用程序的數據彙總在一起 – Tarlen

相關問題