我有一个查询,显示去年通过我的系统发送了多少条消息,按月分组。效果很好!
结果如下:
+------+-------+--------+--------+--------+
| Year | Month | Type 1 | Type 2 | Type 3 |
+------+-------+--------+--------+--------+
| 2013 | 10 | 0 | 2 | 3 |
| 2013 | 11 | 4 | 21 | 56 |
| 2013 | 12 | 1 | 10 | 16 |
| 2014 | 1 | 2 | 10 | 52 |
| 2014 | 2 | 1 | 62 | 118 |
+------+-------+--------+--------+--------+
(类型1,2和3只是不同类型的USERS - 以此为准)
但是,我想避免每个月在结果集中显示两次相同的接收器(msg_receiver)。
因此,如果用户44和39在12月向用户70发送消息,则user_id 70将仅计算在12月的ONCE。目前,他将出现两次。
以下是我的询问:
SELECT
Year(m.msg_date) as year,
Month(m.msg_date) as month,
sum(u.type = '1') as type_1,
Sum(u.type = '2') as type_2,
sum(u.type = '7') as type_3
FROM
messages m
INNER JOIN
users u ON u.user_id = m.msg_sender
WHERE
m.msg_date >= CURDATE() - INTERVAL 1 YEAR
AND month(msg_date) != month(curdate())
GROUP BY
Month(m.msg_date) -- , m.msg_receiver (this does not work, it will no longer group by each month/year).
ORDER BY
msg_date
对此的逻辑答案,在我的选择中,首先按月分组,然后是user_id(或者副通道)。但如果我这样做,结果看起来很奇怪。参见:
使用GROUP BY Month(m.msg_date), u.user_id
+------+-------+--------+--------+--------+
| Year | Month | Type 1 | Type 2 | Type 3 |
+------+-------+--------+--------+--------+
| 2013 | 10 | 0 | 1 | 0 |
| 2013 | 10 | 0 | 0 | 1 |
| 2013 | 10 | 0 | 0 | 1 |
| 2013 | 10 | 0 | 1 | 0 |
| 2013 | 10 | 0 | 0 | 1 |
| 2013 | 11 | 0 | 0 | 19 |
| 2013 | 11 | 0 | 1 | 0 |
| 2013 | 11 | 0 | 1 | 0 |
| 2013 | 11 | 0 | 1 | 0 |
| 2013 | 11 | 0 | 1 | 0 |
| 2013 | 11 | 2 | 0 | 0 |
| 2013 | 11 | 0 | 0 | 11 |
+------+-------+--------+--------+--------+
它不再按月分组,因为它应该。
有什么想法吗?
修改
只是为了澄清我想要实现的目标,因为人们有点困惑。想象一下这种情况:
It is December 2013.
USER 1 has written 5 messages to USER 2 (this should count as 1 in december)
USER 4 has written 1 message to USER 4 (this should count as 1 in december)
USER 3 has written 2 messages to USER 4 and 2 (this should count as 2 in december).
The totals of the month would then be 4. Because there has been 4 conversations.
有意义吗?我发现自己经常在如何正确地表达自我和理解中苦苦挣扎。
答案 0 :(得分:3)
您可以使用COUNT(DISTINCT
仅对每种类型的msg_receiver
计算一次:
SELECT
Year(m.msg_date) as year,
Month(m.msg_date) as month,
COUNT(DISTINCT CASE WHEN u.type = '1' THEN m.msg_receiver END) as type_1,
COUNT(DISTINCT CASE WHEN u.type = '2' THEN m.msg_receiver END) as type_2,
COUNT(DISTINCT CASE WHEN u.type = '3' THEN m.msg_receiver END) as type_3
FROM
messages m
INNER JOIN
users u ON u.user_id = m.msg_sender
WHERE
m.msg_date >= CURDATE() - INTERVAL 1 YEAR
AND month(msg_date) != month(curdate())
GROUP BY
Year(m.msg_date), Month(m.msg_date)
ORDER BY
msg_date
N.B我已将Year(m.msg_date)
添加到您的论坛,以确保结果是确定的
如果同一个用户收到来自两个不同类型的消息,这两个用户有两种不同的类型,那么它们将被计入两种类型。如果这不是预期的结果,您需要提出一些逻辑,说明它们应该计入哪种类型(最小值,最大值,模式,中位数等)
例如,如果您想要最小用户类型,则可以使用:
SELECT
m.year,
m.month,
sum(m.type = '1') as type_1,
Sum(m.type = '2') as type_2,
sum(m.type = '7') as type_3
FROM (
SELECT
Year(m.msg_date) as year,
Month(m.msg_date) as month,
m.msg_receiver,
MIN(u.type) AS type
FROM
messages m
INNER JOIN
users u ON u.user_id = m.msg_sender
WHERE
m.msg_date >= CURDATE() - INTERVAL 1 YEAR
AND month(msg_date) != month(curdate())
GROUP BY
Year(m.msg_date), Month(m.msg_date), m.msg_receiver
) m
GROUP BY
m.Year, m.Month
ORDER BY
m.year, m.month;
修改强>
在回答您更新后的问题时,我的第一个答案会将您的示例计为仅有3个会话而不是4个,因为只有3个唯一收件人。你真正需要的是能够统计发送者和接收者,即count(distinct m.msg_sender, m.msg_sender)
。不幸的是,这不是有效的语法,但是,你可以通过连接两个字段来实现基本相同的东西(只要它们被一个不能出现的字符/字符分开。例如
SELECT
Year(m.msg_date) as year,
Month(m.msg_date) as month,
COUNT(DISTINCT CASE WHEN u.type = '1' THEN CONCAT(m.msg_sender, '|', m.msg_receiver) END) as type_1,
COUNT(DISTINCT CASE WHEN u.type = '2' THEN CONCAT(m.msg_sender, '|', m.msg_receiver) END) as type_2,
COUNT(DISTINCT CASE WHEN u.type = '3' THEN CONCAT(m.msg_sender, '|', m.msg_receiver) END) as type_3
FROM
messages m
INNER JOIN
users u ON u.user_id = m.msg_sender
WHERE
m.msg_date >= CURDATE() - INTERVAL 1 YEAR
AND month(msg_date) != month(curdate())
GROUP BY
Year(m.msg_date), Month(m.msg_date)
ORDER BY
msg_date
答案 1 :(得分:0)
您尚未发布数据结构,但似乎您想要将INNER JOIN更改为
INNER JOIN
users u ON u.user_id = m.msg_receiver