У меня есть одна таблица с именем viewlist следующим образом
Id article_id viewdate
--------------------------------------------------
1 1 2015-07-01
2 1 2015-07-01
3 1 2015-07-01
4 2 2015-07-01
5 2 2015-07-01
6 1 2015-07-02
7 2 2015-07-02
8 1 2015-07-03
9 2 2015-07-03
10 1 2015-07-08
11 1 2015-07-08
мне нужно написать запрос MySQL, чтобы получить количество и article_id путем группировки смежного поля viewdate
хотел получить результат следующим образом
article_id count date_period
-----------------------------------------------------------------
1 4 2015-07-01 - 2015-07-02
2 3 2015-07-01 - 2015-07-02
1 3 2015-07-03 - 2015-07-08
2 1 2015-07-03 - 2015-07-08
Есть ли простой запрос, чтобы получить этот тип результата?
Следующий запрос может быть полезным. но я не уверен, что это может или не может быть практичным для большого применения
SELECT a.range_start
, a.range_end
, b.article_id
, COUNT(b.article_id) total
FROM
( SELECT x.viewdate range_start
, COALESCE(MIN(y.viewdate),MAX(x.viewdate)) range_end
, @i:=@i+1 i
FROM my_table x
LEFT
JOIN my_table y
ON y.viewdate > x.viewdate
JOIN (SELECT @i:=0) vars
GROUP
BY range_start
HAVING MOD(i,2) = 1
) a
LEFT
JOIN my_table b
ON b.viewdate BETWEEN a.range_start AND a.range_end
GROUP
BY article_id
, range_start;
Мое первоначальное решение, по-видимому, имело некоторые проблемы с инициализацией переменной.
Я предполагаю, что исправленное решение ниже обходит эту проблему.
Он использует один небольшой взлом, который может не сработать в будущих версиях систем MySQL (-type), но при необходимости его легко обойти - просто изменив HAVING в подзапросе на WHERE в суперзапросе и добавив куда-нибудь ORDER BY...
SELECT a.range_start
, a.range_end
, b.article_id
, COUNT(*) total
FROM
( SELECT x.viewdate range_start
, MIN(y.viewdate) range_end
, @i:=@i+1 i
FROM my_table x
JOIN my_table y
ON y.viewdate > x.viewdate
JOIN (SELECT @i:=0) vars
GROUP
BY range_start
HAVING MOD(i,2) = 1
) a
JOIN my_table b
ON b.viewdate BETWEEN a.range_start AND a.range_end
GROUP
BY article_id
, range_start;
http://www.sqlfiddle.com/#!9/d753f/3
В ответ на комментарии ниже, что-то вроде следующего может быть способом обработки 'непарных' range_starts - но это не проверено...
SELECT a.range_start
, a.range_end
, b.article_id
, COUNT(b.article_id) total
FROM
( SELECT x.viewdate range_start
, COALESCE(MIN(y.viewdate),MAX(x.viewdate)) range_end
, @i:=@i+1 i
FROM my_table x
LEFT
JOIN my_table y
ON y.viewdate > x.viewdate
JOIN (SELECT @i:=0) vars
GROUP
BY range_start
HAVING MOD(i,2) = 1
) a
LEFT
JOIN my_table b
ON b.viewdate BETWEEN a.range_start AND a.range_end
GROUP
BY article_id
, range_start;
select article_id, count(article_id), concat(min(viewdate),' - ', max(viewdate)) from 'tablename' group by article_id
Попробуйте это может быть работа.
1 7 2015-07-01 2015-07-08, 2 4 2015-07-01 2015-07-03