按月/年查询多个表和组

时间:2015-12-17 18:53:45

标签: mysql

我正在使用3个表格: 用户(ID,名字,姓氏,类型,禁用) 评论(ID,发件人,日期) comment_recipient(COMMENT_ID,USER_ID)

我试图找到给定或收到某个月/年评论的用户的数据。我想要的结果行: 名字|姓氏|评论给出了|收到的评论|月|年

单个评论可以有多个收件人(comment_recipient中有许多条目)

我开始关注这个问题,看起来有点类似: PubNub Access Manager to lock down access to your channels

以下是我目前的情况:

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

我只是在使用&#39; 24&#39;为了收到&#39;目前,我正试图一次解决这个问题

我不需要计算每个用户或每个月,所以如果给定和收到它们都会返回0,则可以忽略它们

2 个答案:

答案 0 :(得分:1)

如果你把它分成两部分,我认为这个问题会更容易解决。

  1. 计算用户每月发送的邮件数
  2. 计算用户每月收到的邮件数
  3. 您可以使用联合“合并”发送和接收的消息。

    完整查询可能如下所示:

    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;
    

答案 1 :(得分:0)

您将从表中生成三个汇总数据集。他们是

  1. 一组月末日期
  2. 发送的评论摘要。
  3. 收到的意见摘要。
  4. 然后你可以一起加入他们

    您需要为每个子查询提供子查询。从月末日期开始。

                            SELECT DISTINCT LAST_DAY(`date`) month_end
                              FROM comment
    

    您需要发送的评论,按用户ID和月份汇总

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

    您需要收到的评论,按用户ID和月份汇总。这需要加入评论表,以获取评论的日期。

                            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操作的原因。我们还必须在单独的查询中进行聚合。如果我们只是加入评论和收件人,我们最终会有很多重复。