这是我提出的按月分组的解决方案。我在本地 MySQL 安装中使用了您的数据来测试结果:
SELECT
COUNT(*) AS cnt,
GROUP_CONCAT(b.id ORDER BY b.id) AS user_ids,
a.monthgroup
FROM
(
SELECT MONTH(FROM_UNIXTIME(modified_time)) AS monthgroup
FROM jb_resumes
WHERE modified_time BETWEEN
UNIX_TIMESTAMP('2012-03-01 00:00:00')
AND UNIX_TIMESTAMP('2012-04-30 23:59:59')
GROUP BY monthgroup
) a
CROSS JOIN
jb_users b
LEFT JOIN
jb_resumes c ON
b.id = c.user_id
AND a.monthgroup = MONTH(FROM_UNIXTIME(modified_time))
WHERE
b.signup_time < UNIX_TIMESTAMP('2012-04-30 23:59:59')
AND c.user_id IS NULL
GROUP BY
a.monthgroup
ORDER BY
a.monthgroup
这有点笨拙,所以我要看看我是否能想出一个更优雅的解决方案。
日分组解决方案:
SELECT
COUNT(*) AS cnt,
GROUP_CONCAT(b.id ORDER BY b.id) AS user_ids,
a.daygroup
FROM
(
SELECT MAKEDATE(YEAR(FROM_UNIXTIME(modified_time)), DAYOFYEAR(FROM_UNIXTIME(modified_time))) AS daygroup
FROM jb_resumes
WHERE modified_time BETWEEN
UNIX_TIMESTAMP('2012-03-01 00:00:00')
AND UNIX_TIMESTAMP('2012-04-30 23:59:59')
GROUP BY daygroup
) a
CROSS JOIN
jb_users b
LEFT JOIN
jb_resumes c ON
b.id = c.user_id
AND a.daygroup = MAKEDATE(YEAR(FROM_UNIXTIME(modified_time)), DAYOFYEAR(FROM_UNIXTIME(modified_time)))
WHERE
b.signup_time < UNIX_TIMESTAMP('2012-04-30 23:59:59')
AND c.user_id IS NULL
GROUP BY
a.daygroup
ORDER BY
a.daygroup
编辑:月份分组查询的解释:
由于您要求对解决方案进行解释,因此我是这样想的:
我们首先要做的是从modified_time
一个时间范围内的所有 s 中提取月份分组:
SELECT MONTH(FROM_UNIXTIME(modified_time)) AS monthgroup
FROM jb_resumes
WHERE modified_time BETWEEN
UNIX_TIMESTAMP('2012-03-01 00:00:00')
AND UNIX_TIMESTAMP('2012-04-30 23:59:59')
GROUP BY monthgroup
导致:
然后为了比较monthgroup
每个用户的组合,找出哪些用户在 内没有修改时间,我们必须在和所有用户monthgroup
之间做一个笛卡尔积。monthgroup
由于上面的查询已经使用 a GROUP BY
,我们不能直接加入该查询,而是必须将其包装在一个子选择中才能进入FROM
子句:
SELECT
a.monthgroup,
b.*
FROM
(
SELECT MONTH(FROM_UNIXTIME(modified_time)) AS monthgroup
FROM jb_resumes
WHERE modified_time BETWEEN
UNIX_TIMESTAMP('2012-03-01 00:00:00')
AND UNIX_TIMESTAMP('2012-04-30 23:59:59')
GROUP BY monthgroup
) a
CROSS JOIN
jb_users b
--
ORDER BY a.monthgroup, b.id #for clarity's sake
导致:
现在我们有了monthgroup
s 和 all id
s 的组合,但是我们不想包括晚于时间范围的用户,所以我们通过在我们的子句signup_time
中引入第一个条件来过滤掉它们:WHERE
SELECT
a.monthgroup,
b.*
FROM
(
SELECT MONTH(FROM_UNIXTIME(modified_time)) AS monthgroup
FROM jb_resumes
WHERE modified_time BETWEEN
UNIX_TIMESTAMP('2012-03-01 00:00:00')
AND UNIX_TIMESTAMP('2012-04-30 23:59:59')
GROUP BY monthgroup
) a
CROSS JOIN
jb_users b
WHERE
b.signup_time < UNIX_TIMESTAMP('2012-04-30 23:59:59')
--
ORDER BY a.monthgroup, b.id #for clarity's sake
导致:
通知id
1
已被过滤掉。现在我们可以通过以下方式进行比较LEFT JOIN
:
SELECT
a.monthgroup,
b.*,
c.*
FROM
(
SELECT MONTH(FROM_UNIXTIME(modified_time)) AS monthgroup
FROM jb_resumes
WHERE modified_time BETWEEN
UNIX_TIMESTAMP('2012-03-01 00:00:00')
AND UNIX_TIMESTAMP('2012-04-30 23:59:59')
GROUP BY monthgroup
) a
CROSS JOIN
jb_users b
LEFT JOIN
jb_resumes c ON
b.id = c.user_id
AND a.monthgroup = MONTH(FROM_UNIXTIME(modified_time))
WHERE
b.signup_time < UNIX_TIMESTAMP('2012-04-30 23:59:59')
--
ORDER BY a.monthgroup, b.id #for clarity's sake
导致:
在这里,我们LEFT JOIN
的条件是用户在其中进行了简历修改,jb_resumes
并且修改发生在该monthgroup
值的月份内。如果用户在该月没有修改简历,则LEFT JOIN
返回NULL
表中的值。我们希望那些条件不满足的用户,因此我们必须将第二个条件放在WHERE
子句中:
SELECT
a.monthgroup,
b.*,
c.*
FROM
(
SELECT MONTH(FROM_UNIXTIME(modified_time)) AS monthgroup
FROM jb_resumes
WHERE modified_time BETWEEN
UNIX_TIMESTAMP('2012-03-01 00:00:00')
AND UNIX_TIMESTAMP('2012-04-30 23:59:59')
GROUP BY monthgroup
) a
CROSS JOIN
jb_users b
LEFT JOIN
jb_resumes c ON
b.id = c.user_id
AND a.monthgroup = MONTH(FROM_UNIXTIME(modified_time))
WHERE
b.signup_time < UNIX_TIMESTAMP('2012-04-30 23:59:59')
AND c.user_id IS NULL
--
ORDER BY a.monthgroup, b.id #for clarity's sake
导致:
最后,我们可以在monthgroup
字段上进行分组并放入我们的COUNT()
和GROUP_CONCAT()
函数:
SELECT
COUNT(*) AS cnt,
GROUP_CONCAT(b.id ORDER BY b.id) AS user_ids,
a.monthgroup
FROM
(
SELECT MONTH(FROM_UNIXTIME(modified_time)) AS monthgroup
FROM jb_resumes
WHERE modified_time BETWEEN
UNIX_TIMESTAMP('2012-03-01 00:00:00')
AND UNIX_TIMESTAMP('2012-04-30 23:59:59')
GROUP BY monthgroup
) a
CROSS JOIN
jb_users b
LEFT JOIN
jb_resumes c ON
b.id = c.user_id
AND a.monthgroup = MONTH(FROM_UNIXTIME(modified_time))
WHERE
b.signup_time < UNIX_TIMESTAMP('2012-04-30 23:59:59')
AND c.user_id IS NULL
GROUP BY
a.monthgroup
ORDER BY
a.monthgroup
给我们想要的结果: