2015-12-17 61 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操作。我们还必须在单独的查询中进行汇总。如果我们只是简单地加入评论和收件人,我们最终会得到很多重复。