Вот решение, которое я придумал для группировки по месяцам. Я использовал свои данные в моей локальной установки 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
Edit: Объяснение месяца группирования запроса:
Поскольку вы попросили для объяснения решения, вот как я понял это :
Что мы должны в первую очередь сделать, это извлечь группы месяцев из всех modified_time
с в течение периода времени:
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
и всеми пользователями. Так как запрос выше уже использует 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 и все id
s, но мы не хотим включать пользователей, у которых есть signup_time
, позже, чем временной диапазон, поэтому мы отфильтровываем их, вводя первое условие в нашем WHERE
clau себе:
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
Предоставление нам желаемого результата:
Я полностью спутать этим утверждением: > по дате, когда они не имеют резюме закачано Так, гм, вам это нужно, сгруппированные по дата, когда они не представили резюме? –
Вы хотите, чтобы группа была днем или месяцем? Различные запросы или в одном запросе? –
@SomnathMuluk - Мне нужно сгруппировать его по дням, неделям и месяцам. – Pateman