Можно ли все это одним запросом?

idencial

Одинаковый
Можно ли все это одним запросом?

Смысл проблемы в следующем:
Требуется реализовать динамику посещений за последние 30 дней.
Посчитать нужно, к примеру, хиты и хосты, но выводить надо не просто хиты и хосты за определнный день, а хиты и хосты нарастающим итогом (это скорее относится к хостам, т.к они уникальные), т.е нужно выводить последовательно, хиты и хосты, посчитанные за определенный интервал времени (этот интервал ес-но растет от 1 дня к 30).
структура базы стандартная
ip | datetime | url

сейчас делаю так:
PHP:
$result_date = mysql_query("SELECT DATE_FORMAT(datetime, '%Y-%m-%d') as date FROM stat where (DATE_FORMAT(datetime, '%Y-%m-%d') >= date_sub(DATE_FORMAT('$date', '%Y-%m-%d'), interval 1 month) AND DATE_FORMAT(datetime, '%Y-%m-%d') <= DATE_FORMAT('$date', '%Y-%m-%d')) group by date order by date desc");
for($i=0; $i<mysql_num_rows($result_date); $i++) { 
     $output_date = mysql_fetch_array($result_date);
     $result_hits = mysql_query("SELECT count(url) as hits FROM stat where (DATE_FORMAT(datetime, '%Y-%m-%d') >= date_sub(DATE_FORMAT('$date', '%Y-%m-%d'), interval 1 month) AND DATE_FORMAT(datetime, '%Y-%m-%d') <= '$output_date[date]')");
     $result_hosts = mysql_query("SELECT count(DISTINCT(ip)) as hosts FROM $tablename[page_stat] where (DATE_FORMAT(datetime, '%Y-%m-%d') >= date_sub(DATE_FORMAT('$date', '%Y-%m-%d'), interval 1 month) AND DATE_FORMAT(datetime, '%Y-%m-%d') <= '$output_date[date]')");
}
Смысл проблемы в том, что я не могу посчитать хиты и хосты одним запросом, т.к тогда нужно использовать group by, а он здесь нахрен не нужен.

Может кто видит решение проблемы более простым способом?
 

Demiurg

Guest
при выводе подсчитывай нарастающий итог с помощью php.
 

idencial

Одинаковый
Это было бы слишком просто.
Ведь там в запросе count(DISTINCT(ip)), т.е простая сумма здесь только для хитов подойдет.
А у меня в реалии уникальность идет не только по хитам, т.е запросов даже не два
 

idencial

Одинаковый
Таким запросом я получаю хиты и хосты просто за каждый день, никакого нарастающего итога.
А мне надо, чтобы за каждый следующий день count(distinct ip)
был не за этот день, а за временной интервал от начального дня до этого.
Т.е я хочу видеть, например, месячную и недельную аудиторию
 

chira

Новичок
select count(*) , count(distinct t1.ip)
from table t1, table t2
where t1.date < t2.date
and t1.date between 'd1' and 'd2'
and t2.date >='d2'
group by t2.date;
 

Demiurg

Guest
я же тебе сказал, делай "нарастающий" средствами php
 

idencial

Одинаковый
2 chira спасибо за идею самообъединения

2 Demiurg
Ты, видимо, не правильно понял что мне надо (нарастающий не всегда сумма)
При конструкции count(distinct ip) и плавающем интервале выборки php тут ничего не сделает, только запрос

ЗЫ. СУММА=НАРАСТАЮЩИЙ только для хитов (хосты же уникальные)
 

idencial

Одинаковый
Стал пробовать объединение, думал все быстро олучится и накнулся на такую проблему.
Использую такой запрос:
PHP:
SELECT count(a.url) as hits, count(DISTINCT(a.ip)) as hosts, count(DISTINCT(a.stat_cookies)) as visitors, DATE_FORMAT(b.datetime, '%Y-%m-%d') as bdate FROM page_stat as a, page_stat as b where (DATE_FORMAT(b.datetime, '%Y-%m-%d') >= date_sub(DATE_FORMAT('2003-02-12', '%Y-%m-%d'), interval 1 month) AND DATE_FORMAT(b.datetime, '%Y-%m-%d') <= DATE_FORMAT('2003-02-12', '%Y-%m-%d')) and (DATE_FORMAT(a.datetime, '%Y-%m-%d') >= DATE_FORMAT(b.datetime, '%Y-%m-%d') AND DATE_FORMAT(a.datetime, '%Y-%m-%d') <= DATE_FORMAT('2003-02-12', '%Y-%m-%d')) group by bdate order by bdate desc
Он мне выдает
Error 1104: The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok

Я так понимаю это связано с параметром max_join_size rows.
Или может что в запросе не то?
 

Demiurg

Guest
>DATE_FORMAT(b.datetime, '%Y-%m-%d') <= DATE_FORMAT('2003-02-12', '%Y-%m-%d'))
никогда не делай такие условия, даже если на поле будет стоять индекс он использоваться не будет.
 

idencial

Одинаковый
Сделал
PHP:
SELECT count(a.url) as hits, count(DISTINCT(a.ip)) as hosts, count(DISTINCT(a.stat_cookies)) as visitors, DATE_FORMAT(b.datetime, '%Y-%m-%d') as bdate FROM page_stat as a, page_stat as b where (b.datetime >= date_sub('2003-02-12', interval 1 month) AND b.datetime <= '2003-02-12') and (a.datetime >= b.datetime AND a.datetime <= '2003-02-12') group by bdate order by bdate desc
К сожалению выдает ту же ошибку
Подскажите где я лошу =)
 

Demiurg

Guest
сколько записей в таблице ?

ps а это зачем : date_sub('2003-02-12', interval 1 month) ?
на производительность это конечно не влияет, но я бы написал просто '2003-01-12' :)
 

idencial

Одинаковый
сколько записей в таблице ?
Порядка 30 тысяч, но будет раза в 3 больше.

ps а это зачем : date_sub('2003-02-12', interval 1 month) ?
Потому что я не '2003-02-12' вставляю, а ту дату, которую я выберу в календаре, т.е выбираю дату в календаре и относительно ее я считаю статистику за предыдущий месяц.

ЗЫ. Самое удивительное, что если делать просто цикл на 30 дней, а в нем еще по 3 запроса, т.е в итоге 90 запросов, то хоть и долго, но работает.
Вот я и думал, что сделать один навороченный всесто 90 простых будет лучше, но пока что-то не пашет =(
 

Demiurg

Guest
На дату было бы неплохо индекс поставить. Но если у тебя постоянные добавления идут тебе надо систему с двумя таблтцам делать. В одну вставлять и во вторую раз в день/неделю/месяц делать выжимку.
 

Demiurg

Guest
>Потому что я не '2003-02-12' вставляю, а ту дату, которую я выберу в календаре, т.е выбираю дату в календаре и >относительно ее я считаю статистику за предыдущий месяц.
так ты в скриптах вычитай месяц, все равно дату надо проверять перед тем, как в запрос пихать.
 

idencial

Одинаковый
так ты в скриптах вычитай месяц, все равно дату надо проверять перед тем, как в запрос пихать.
Это конечно можно, но неужели так много ресурсов жрет
date_sub?
 

Demiurg

Guest
>Это конечно можно, но неужели так много ресурсов жрет
нет, это вычисляется один раз, просто смотриться страшно :)
 
Сверху