ФорумРазработкаБазы данных → разбиение данных по временным промежуткам

разбиение данных по временным промежуткам

  • Argnist

    Сообщения: 130 Репутация: N Группа: Кто попало

    Spritz 9 июля 2010 г. 3:36

    Есть табличка:
    id int
    time datetime

    уникальные пара (id, time)

    Можно ли одним SQL запросом подсчитать кол-во id для нескольких промежутков времени? Например, за последнюю неделю кол-во уникальных id для каждого часа?
    Выход:
    [table]
    [tr][td]count(id)[/td][td]Y-m-d H1-H2[/td][/tr]
    [tr][td]34[/td][td]2010-07-09 10-11[/td][/tr]
    [tr][td]46[/td][td]2010-07-09 09-10[/td][/tr]
    [tr][td]11[/td][td]2010-07-09 08-09[/td][/tr]
    [/table]
    и т.д.
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 9 июля 2010 г. 4:09, спустя 32 минуты 35 секунд

    тебе нужен какой-то "round" для поля ДатаВремя. поройся в доках
    ιιlllιlllι унц-унц
  • Argnist

    Сообщения: 130 Репутация: N Группа: Кто попало

    Spritz 9 июля 2010 г. 4:17, спустя 7 минут 45 секунд

    не обязательно по часам, может быть и 15минутный промежуток) самое главное не знаю как сгенерировать это разбиение
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 9 июля 2010 г. 4:25, спустя 8 минут 22 секунды

    group by round (unix_timestamp(time) / 900) = 15 минутные промежутки :)
    Сапожник без сапог
  • Argnist

    Сообщения: 130 Репутация: N Группа: Кто попало

    Spritz 9 июля 2010 г. 4:55, спустя 30 минут 15 секунд

    чет явно не то, не совпадает с кучей отдельных селектов)
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 9 июля 2010 г. 5:01, спустя 5 минут 23 секунды


    чет явно не то, не совпадает с кучей отдельных селектов)
    покажи как использовал запрос
    Сапожник без сапог
  • Argnist

    Сообщения: 130 Репутация: N Группа: Кто попало

    Spritz 9 июля 2010 г. 5:08, спустя 7 минут 19 секунд

    короче вот такое надо переделать в 1 запрос :)


    $yesterday = mktime($hour, 0, 0, $month, $day, $year) - 86400;
    $interval = 900; // 15 минут

    for ($i = 0; $i <= $total; $i += $interval)
    {
    $cur_e = date("Y-m-d H:i:s", $yesterday - $i);
    $cur_b = date("Y-m-d H:i:s", $yesterday - $i - $interval);
    $res = mysql_query("SELECT COUNT(DISTINCT login) AS count FROM visits
    WHERE visit_begin <= '$cur_e' AND visit_end >= '$cur_b' ");

    }
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 9 июля 2010 г. 5:17, спустя 8 минут 55 секунд

    Argnist, говно какое-то.
    1. в начале темы ты упоминал одно поле с датой, а тут два. не заморачивайся так - только запутаешь себя.
    2. что в данном контексте тебе даёт distinct ???
    3. если есть группировка по какому-то полю - должен быть GROUP BY поле. это логически понятно (надеюсь)
    ιιlllιlllι унц-унц
  • Argnist

    Сообщения: 130 Репутация: N Группа: Кто попало

    Spritz 9 июля 2010 г. 5:27, спустя 10 минут

    1) да не важно 1 дата или нет, главное чтоб попадала в сгенерированные промежутки cur_b - cur_e, остальное я допилю как надо
    2) login в таблице не уникальный, Group by по логину не проходит, только с Distinct, тут не надо трогать)
    Спустя 204 сек.
    Group by по логину вернет кол-во записей для каждого уникального логина для каждого промежутка времени, а мне надо кол-во уникальных логинов для каждого промежутка времени
    Спустя 23 сек.
    поэтому Distinct =)
  • Givi

    Сообщения: 2284 Репутация: N Группа: Адекваты

    Spritz 9 июля 2010 г. 5:29, спустя 1 минуту 42 секунды

    Argnist, если выбираешь кол-во посетителей за последние 15 минут, то логичнее все же сделать как говорить а2д2 - выбрать всех за такой-то промежуток времени, и сгруппировать по имени. Полученный результат посчитать с помощью mysql_num_rows()
  • Argnist

    Сообщения: 130 Репутация: N Группа: Кто попало

    Spritz 9 июля 2010 г. 5:34, спустя 5 минут 11 секунд

    не за последние! а за $total = неделя, месяц год? и тд)) в этом и проблема, все работает, но тыщи отдельных запросов как-то не оч
  • artoodetoo

    Сообщения: 5139 Репутация: N Группа: в ухо

    Spritz 9 июля 2010 г. 5:58, спустя 24 минуты

    вот чтобы небыло тыщ, делай group by. а чтобы мозг твой не расплавился что именно группировать - группируй по одному полю времени (+ опционально по полю id)
    схематично - я использую тип INT для времени - для простоты:

    $sql = "SELECT round(({$now}-v.visited)/{$interval}) AS ago, count(*) AS cnt
    FROM `visits` AS v
    GROUP BY ago";

    мне таки кажется, что цель посчитать количество заходов за интервал, а не количество заходов по пользователям, поэтому здесь группировка только по усеченному времени
    ιιlllιlllι унц-унц
  • Givi

    Сообщения: 2284 Репутация: N Группа: Адекваты

    Spritz 9 июля 2010 г. 6:12, спустя 14 минут 5 секунд

    Argnist, тогда алгоритм по типу такого:
    1. Выбираем все записи за нужным нам период (берем логин и даты) из базы и кладем в массив. Сортировка по дате должна быть
    2. Проходимся по циклу, попутно проверяя на время + уникальность логина в данном диапазоне времени, делаем после каждого "тру" +1 к счетчику.
    3. Выводим что нужно куда нужно

    Представим что массив уже есть:
    $array = array();
    $array[] = array('time'=>10-10-2010 14:25,'login'=>'Dud');
    $array[] = array('time'=>10-10-2010 14:28,'login'=>'Argnist');
    $array[] = array('time'=>10-10-2010 14:35,'login'=>'Dud');
    $array[] = array('time'=>10-10-2010 14:55,'login'=>'md5');

    function get_start_stop($start) {
       $interval = 15; // тут ставишь свой временной интервал, только в правильной "валюте". Сам с этим разбирайся
       return array('start'=>$start,'stop'=>$start+$interval);
    }

    $result = array();
    $login = array();
    foreach ($array as $k=>$v)
    {
       if ($v['time'] > $youtime['start'] AND $v['time'] <= $youtime['stop'])
       {
            if (array_key_exists($v['login'],$login) === false)
            {
                $login[$v['login']] = 1;
            }
       }
       else
       {
            $result[ $youtime['start'].'-'.$youtime['stop']] = count($login);
            $youtime = get_start_stop($youtime['stop']);
            $login = array();
       }
    }


    Вот примерно так. Дальше подгоняй под себя сам.
    Спустя 142 сек.
    Хотя бля, не, не совсем то. Точнее, направление такое, но я уже понял что это совсем неправильно, ибо пропуски будут. В общем, ну его нах, буду работать лучше.
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 9 июля 2010 г. 6:17, спустя 4 минуты 39 секунд

    олол, пиздец устроили тут :D
    Сапожник без сапог
  • Givi

    Сообщения: 2284 Репутация: N Группа: Адекваты

    Spritz 9 июля 2010 г. 6:18, спустя 1 минуту 42 секунды

    phpdude, йопт, не одному тебе флудерастией заниматься.
    Да и вообще как-то ведь нужно от работы на пару минут отвлекаться.

Пожалуйста, авторизуйтесь, чтобы написать комментарий!