Ваше конкретное приложение делает это довольно просто, я думать. Если у вас есть «n» отдельных дат в «n'-дневном интервале», то «n» разных дат должно быть быть последовательным.
Пролистайте нижнюю часть для общего решения, которое требует только общих выражений таблицы и перехода на PostgreSQL. (Шучу. Я реализовал в PostgreSQL, потому что я не хватает времени.)
create table ForumPost (
ID integer primary key,
UserID integer not null,
post_date date not null
);
insert into forumpost values
(1, 1, '2013-01-15'),
(2, 1, '2013-01-16'),
(3, 1, '2013-01-17'),
(4, 1, '2013-01-18'),
(5, 1, '2013-01-19'),
(6, 1, '2013-01-20'),
(7, 1, '2013-01-21'),
(11, 2, '2013-01-15'),
(12, 2, '2013-01-16'),
(13, 2, '2013-01-17'),
(16, 2, '2013-01-17'),
(14, 2, '2013-01-18'),
(15, 2, '2013-01-19'),
(21, 3, '2013-01-17'),
(22, 3, '2013-01-17'),
(23, 3, '2013-01-17'),
(24, 3, '2013-01-17'),
(25, 3, '2013-01-17'),
(26, 3, '2013-01-17'),
(27, 3, '2013-01-17');
Теперь давайте посмотрим на выходе этого запроса. Для краткости я просматриваю 5-дневные интервалы, а не 30-дневные интервалы.
select userid, count(distinct post_date) distinct_dates
from forumpost
where post_date between '2013-01-15' and '2013-01-19'
group by userid;
USERID DISTINCT_DATES
1 5
2 5
3 1
Для пользователей, которые соответствуют критериям, число различных дат в этом 5-дневном интервале должны быть 5, верно? Поэтому нам просто нужно добавить эту логику в предложение HAVING.
select userid, count(distinct post_date) distinct_dates
from forumpost
where post_date between '2013-01-15' and '2013-01-19'
group by userid
having count(distinct post_date) = 5;
USERID DISTINCT_DATES
1 5
2 5
Более общее решение
Это действительно не имеет смысла говорить, что, если вы разместите каждый день от 2013-01-01 до 2013-01-31, вы 'отправил 30 дней подряд 2 раза. Вместо этого я ожидаю, что часы начнутся в 2013-01-31 годах. Мои извинения за внедрение в PostgreSQL; Я попытаюсь реализовать в T-SQL позже.
with first_posts as (
select userid, min(post_date) first_post_date
from forumpost
group by userid
),
period_intervals as (
select userid, first_post_date period_start,
(first_post_date + interval '4' day)::date period_end
from first_posts
), user_specific_intervals as (
select
userid,
(period_start + (n || ' days')::interval)::date as period_start,
(period_end + (n || ' days')::interval)::date as period_end
from period_intervals, generate_series(0, 30, 5) n
)
select userid, period_start, period_end,
(select count(distinct post_date)
from forumpost
where forumpost.post_date between period_start and period_end
and userid = forumpost.userid) distinct_dates
from user_specific_intervals
order by userid, period_start;
Какая СУБД вы используете? Postgres? Oracle? –
SQL Server 2008 r2 –
использовать подзапрос для всех сообщений в диапазоне дат 30 дней назад, по дате и подсчету. Проверьте, если 30? –