2015-12-17 131 views
1

我有3代表工作: 用戶(ID,名字,姓氏,類型,禁用) 評論(ID,發件人,日期) comment_recipient(COMMENT_ID,USER_ID)查詢多個表和組按月/年

我正在嘗試查找給出或接收給定月份/年的評論的用戶的數據。我想要的結果行: 名字|姓氏|給出的評論|收到的評論|月|

年爲單個註釋可以有多個收件人(許多條目comment_recipient)

我開始關注此問題,這似乎有點類似: group-by-month-and-year-count-from-another-table

這是我目前有:

SELECT 
    firstName AS 'First Name', 
    lastName AS 'Last Name', 
    given AS 'Comments Given', 
    received AS 'Comments Received', 
    MONTHNAME(d_yearmonth) AS Month, 
    YEAR(d_yearmonth) AS Year 
FROM (
    SELECT 
    LAST_DAY(c.date) AS d_yearmonth, 
    u.firstName, 
    u.lastName, 
    (SELECT COUNT(*) FROM comment AS c1 WHERE c1.sender=c.sender 
    AND LAST_DAY(c1.date)=d_yearmonth) AS given, 
    '24' AS received 
    FROM comment AS c 
    JOIN comment_recipient AS cr ON cr.comment_id=c.id 
    JOIN user AS u ON u.id=c.sender 
    WHERE u.type<4 AND u.disabled=0 
    GROUP BY 
    d_yearmonth 
) AS s 
ORDER BY Year DESC, 
MONTH(d_yearmonth) DESC 

我現在只是使用'24'代表'收到',因爲我試圖在一段時間內計算出1件東西

我不需要計算每個用戶或每個月,因此如果他們在給定和收到時都返回0,他們可以被忽略

回答

1

我認爲如果你打破它,這個問題會容易得多分兩部分。

  1. 計算用戶發送的消息數,每月
  2. 計算

的,你可以使用一個聯盟「合併」的發送和接收的用戶收到的郵件的數量,每月消息。

完整的查詢可能看起來像:

SELECT user_id, 
     lastName, 
     firstName, 
     SUM(sent) as sent, 
     SUM(received) as received, 
     year, 
     month 

FROM (

    SELECT 
     c.sender as user_id, 
     u.lastname as lastName, 
     u.firstname as firstName, 
     count(*) as sent, 
     0 as received, 
     YEAR(date) as year, 
     MONTH(date) as month 
FROM Comment as C 
    JOIN user AS u ON u.id=c.sender 
    WHERE u.type<4 AND u.disabled=0 
GROUP by user_id, year, month 

UNION ALL 

select cr.user_id as user_id, 
     u.lastname as lastName, 
     u.firstname as firstName, 
     0 as sent, 
     count(*) as received, 
     YEAR(date) as year, 
     MONTH(date) as month 
FROM comment_recipient cr 
JOIN comment c ON c.id = cr.comment_id 
JOIN user u on u.id = cr.user_id 
WHERE u.type<4 AND u.disabled=0 
GROUP by user_id, year, month 
) A 
GROUP by user_id, year, month; 
0

你要聯合起來,從你的表產生三個摘要數據集。他們是

  1. 設定結束日期一個月
  2. 發送的評論的摘要。
  3. 收到的意見摘要。

然後你就可以加入他們一起

你需要爲每個這些子查詢。從月末日期開始。

     SELECT DISTINCT LAST_DAY(`date`) month_end 
          FROM comment 

你需要發送的意見,通過用戶名和月

     SELECT COUNT(*) sent, 
           sender id, 
           LAST_DAY(`date`) month_end 
          FROM comment 
         GROUP BY sender, LAST_DAY(`date`) 

總結你需要收集到的意見,通過用戶名和總結了一個月。這需要加入評論表,以獲取評論的日期。

     SELECT COUNT(*) received, 
           cr.user_id id, 
           LAST_DAY(c.`date`) month_end 
          FROM comment_recipient cr 
          JOIN comment c ON cr.comment_id = c.id 
         GROUP BY cr.user_id, LAST_DAY(c.`date`) 

然後,您需要將這三個子查詢(將它們視爲虛擬表)與用戶表連接起來。

SELECT u.firstName, u.lastName, 
     ISNULL(s.sent,0) sent, 
     ISNULL(r.received,0) received, 
     MONTHNAME(d.month_end), YEAR(d.month_end) 
    FROM (
         SELECT DISTINCT LAST_DAY(`date`) month_end 
          FROM comment 
     ) AS d 
    JOIN user u ON 1=1 
    LEFT JOIN (
         SELECT COUNT(*) sent, 
           sender id, 
           LAST_DAY(`date`) month_end 
          FROM comment 
         GROUP BY sender, LAST_DAY(`date`) 
      ) s ON d.month_end=s.month_end AND u.id = s.id 
    LEFT JOIN (
         SELECT COUNT(*) received, 
           cr.user_id id, 
           LAST_DAY(c.`date`) month_end 
          FROM comment_recipient cr 
          JOIN comment c ON cr.comment_id = c.id 
         GROUP BY cr.user_id, LAST_DAY(c.`date`) 
      ) r ON d.month_end=r.month_end AND u.id = r.id 
WHERE u.type < 4 AND u.disabled = 0 
    AND NOT (r.received IS NULL AND s.sent IS NULL) 
    AND d.month_end > CURDATE() - INTERVAL 1 YEAR 

獲得所需的所有行有點棘手。這就是爲什麼我們有ISNULL和LEFT JOIN操作。我們還必須在單獨的查詢中進行彙總。如果我們只是簡單地加入評論和收件人,我們最終會得到很多重複。