2016-04-09 51 views
0

我正在嘗試完成以下任務 - 我希望在每個按日曆周分組的客戶的網站上查看會話。下面是該查詢我到目前爲止做到這一點:MYSQL - 按周分組,同時顯示沒有數值的星期

SELECT o.name 
    , s.organization_id 
    , count(s.id) as num_of_sessions 
    , CONCAT(s.created_at, ' - ', s.created_at + INTERVAL 6 DAY) AS week 
    FROM triton.sessions s 
    , triton.organizations o 
where o.id=s.organization_id 
    and s.organization_id in (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72) 
GROUP BY s.organization_id, WEEK(s.created_at) 
ORDER BY o.name, WEEK(s.created_at); 

這樣做的問題是,與凡客沒有一個網站的會話數週未與0報道 - 而不是周未報。這是一個問題,因爲我無法輕鬆將數據轉化爲Excel,併爲每個客戶的會話創建圖表。

要嘗試解決這個問題,我創建了一個臨時星期表值從1-52每個星期數量和嘗試的方法在這個環節上建議:Summarise by week, even for empty rows

的挑戰是當我做了左外加入,我失去了組織的團隊。

下面是幾個星期以前只是組工作SQL(由組織試圖組前):

select w.weeknum 
    , sess.club 
    , sess.organization_id 
    , count(sess.club) from weeks w 
    left outer 
    join (select o.name as club 
       , s.organization_id 
       , s.created_at 
      from sessions s 
       , organizations o 
      where s.organization_id in (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72) 
      and o.id=s.organization_id 
     ) sess 
    on (w.weeknum = extract(week from sess.created_at)) 
group by w.weeknum 

上面的代碼只是返回52行(各1周),與計給我每週有多少次會話。

我現在想擴展上面的代碼來做上面的事情,但是每個組織。我應該找回52 * N行,其中N是組織的數量。我認爲這將會像將該組織添加到groupby聲明一樣簡單,但是它只是返回了幾周的會話(導致我從一開始就遇到了問題)。以下是查詢:

select w.weeknum 
    , sess.club 
    , sess.organization_id 
    , count(sess.club) 
    from weeks w 
    left outer 
    join (select o.name as club 
       , s.organization_id 
       , s.created_at 
      from sessions s 
       , organizations o 
      where s.organization_id in (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72) 
      and o.id=s.organization_id 
     ) sess 
    on (w.weeknum = extract(week from sess.created_at)) 
group by sess.club, w.weeknum 
order by sess.club 

有沒有人有任何其他建議,我可以實現我的目標?基本上,對於我的每一位客戶,我希望能夠按周查看會話列表(即使他們在特定的一週內沒有會話)。

+0

我想你會得到更好的迴應,如果你縮短你的te xt並格式化您的代碼 –

回答

0

使用cross join讓行,然後left join

select w.weeknum, s.club, s.organization_id, count(s.club) 
from weeks w cross join 
    organizations o left outer join 
    sessions s 
    on w.weeknum = extract(week from s.created_at) and 
     o.id = s.organization_id 
where o.id in (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72) 
group by w.weeknum, s.club, s.organization_id; 
0

只要看看你的原始查詢,並在括號包裹,並用它作爲內嵌視圖。

它看起來像你想出一個行來源,返回所有你想要返回的行,然後左連接到你的內聯視圖。

你有這一部分:

from weeks w 

只是做一個交叉連接到所有要退回的organization_ID的。

它看起來像organization_id可能是組織表的主鍵。如果是這樣的話,那麼這個查詢將返回一組你想要的:

SELECT v.name 
    , v.organization_id 
    FROM triton.organizations v 
WHERE v.organization_id (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72) 
ORDER BY v.organization_id 

所以只是做一個交叉是一套具有weeks行源的加入:

SELECT v.name 
     , v.organization_id 
     , w.weeknum 
    FROM triton.organizations v 
    CROSS 
    JOIN weeks w 
    WHERE v.organization_id (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72) 
    ORDER 
     BY v.organization_id 
     , w.weeknum 

如果你只是想從一個子集weeks表,只需在WHERE子句中添加一個謂詞,例如

AND w.weeknum BETWEEN 0 AND 104 

那應該每個organization_id每weeknum返回給你。

一旦你得到了這個工作,現在只需在原始查詢中添加一個「外部連接」,然後在SELECT列表中添加一個表達式,以獲得與weeknum匹配的值。

我對涉及created_at的表達式感到困惑。返回的created_at的值不確定,因爲GROUP BY。如果您想要「最早」和/或「最新」值,請使用MIN和MAX聚合。 (假設created_at是日期,DATETIME或時間戳。)

SELECT v.name 
     , v.organization_id 
     , w.weeknum 
     , IFNULL(t.num_of_sessions,0) 
    FROM triton.organizations v 
    CROSS 
    JOIN weeks w 
    LEFT 
    JOIN (
      -- query to get session counts goes here 
     ) t 
     ON t.organization_id = v.organization_id 
    AND t.weeknum   = w.weeknum 
    WHERE v.organization_id (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72) 
    ORDER 
     BY v.organization_id 
     , w.weeknum 

在外部查詢,參考視圖返回的num_of_sessions柱。 IFNULL功能是用零替換「缺失」計數的一種便捷方式。

查詢,以獲得「罪狀」可能是這樣的:

  SELECT s.organization_id AS organization_id 
       , WEEK(s.created_at) AS weeknum 
       , COUNT(s.id)   AS num_of_sessions 
       , MIN(s.created_at) AS min_created_at 
       , MAX(s.created_at) AS max_created_at 
      FROM triton.sessions s 
      WHERE s.organization_id IN (17,19,20,21,24,25,26,27,29,31,32,33,34,25,36,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,56,57,58,59,60,62,69,70,72) 
      GROUP 
      BY s.organization_id 
       , WEEK(s.created_at) 

如果原始查詢的這個部分的意圖:

CONCAT(s.created_at, ' - ', s.created_at + INTERVAL 6 DAY) AS week 

是顯示開始日期和結束日期,然後根據周表中的值生成該日期和結束日期。 (如果有一個組織在某一週只有一筆交易,並且是在星期四,那麼這個表達式會在週三之後產生一個「星期四」。這樣做沒有錯,但我強烈懷疑這不是什麼你真正想要的。

如果你想要一個「週日到週六」每個WEEKNUM,倒不如返回從WEEKNUM表。

如果從組織會議要實際日期,然後使用MIN( )和MAX()值created_at,並將它們連接在一起。這些不一定是「星期日到星期六」,但是返回的任何日期都將在星期內「在」。

相關問題