Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Выборка с группировкой записей с разницой во времени меньше 30 минут / 11 сообщений из 11, страница 1 из 1
24.01.2014, 14:52:05
    #38536968
Atletnah
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
Есть таблица(упрощенная) accounting (id, name, registration, id_organization, id_driver)

Водитель привозит технику (id_driver)
Заносится наименование техники (name), дата регистрации (registration), выбирается организация (id_organization)

Необходимо узнать в скольких местах водители были, т.е. выбрать группируя по водителю и по организации.
Но, загвоздка в том, что водитель может привозить несколько единиц техники за выезд, причем дата регистрации отличается (максимум минут 30). А так же водитель может бывать в организации несколько раз за день. Исходя из вышесказанного группировка за день, за час не устраивает.
Т.е каким-то образом необходимо выбирать записи с разницой во времени больше 30 минут
...
Рейтинг: 0 / 0
24.01.2014, 16:15:05
    #38537111
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
Пример входных данных и желаемого результата в студию.
...
Рейтинг: 0 / 0
24.01.2014, 21:11:01
    #38537430
Atletnah
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
CREATE TABLE `test`.`accounting` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 255 ) NOT NULL COMMENT 'Наименование техники',
`registration` DATETIME NOT NULL COMMENT 'Время регистрации техники',
`id_organization` INT NOT NULL COMMENT 'ID организации',
`id_driver` INT NOT NULL COMMENT 'ID водителя'
) ENGINE = INNODB;


INSERT INTO `accounting`
(`id`, `name`, `registration`, `id_organization`, `id_driver`) VALUES
(1, 'HP 1010', '2014-01-12 08:05:00', 1, 1),
(2, 'Canon MF3228', '2014-01-12 08:08:00', 1, 1),
(3, 'Brother 2035', '2014-01-12 08:09:00', 1, 1),
(4, 'HP 2015', '2014-01-12 08:10:00', 1, 1),
(5, 'Kyocera FS-1320', '2014-01-12 08:11:00', 15, 6),
(6, 'Canon lbp2900', '2014-01-12 08:14:00', 15, 6),
(7, 'HP p3005', '2014-01-12 08:18:00', 12, 1),
(8, 'HP p1005', '2014-01-12 08:20:00', 23, 1),
(9, 'Kyocera KM-1620', '2014-01-12 10:20:00', 1, 1),
(10, 'Kyocera FS-1120', '2014-01-12 10:21:00', 2, 1);


id name registration id_organization id_driver1 HP 1010 2014-01-12 08:05:00 1 12 Canon MF3228 2014-01-12 08:08:00 1 13 Brother 2035 2014-01-12 08:09:00 1 14 HP 2015 2014-01-12 08:10:00 1 15 Kyocera FS-1320 2014-01-12 08:11:00 15 66 Canon lbp2900 2014-01-12 08:14:00 15 67 HP p3005 2014-01-12 08:18:00 12 18 HP p1005 2014-01-12 08:20:00 23 19 Kyocera KM-1620 2014-01-12 10:20:00 1 110 Kyocera FS-1120 2014-01-12 10:21:00 2 1

Т.е. необходимо узнать сколько мест водитель объехал.
Каждый из водителей объезжает клиентов и в течении дня может привозить технику по несколько раз.
От каждого клиента может быть по несколько аппаратов за раз.
Техника регистрируется администратором максимум за 15 минут (с запасом пусть будет 30).

Как я понимаю - необходимо сгруппировать по id_driver и id_organizations, а вот что с временем делать не ясно

Должно получиться следующее:

driver_id количество мест объехал 6 1 1 5
...
Рейтинг: 0 / 0
24.01.2014, 22:35:56
    #38537467
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
Тэкс...
Понятно, что первый уровень группировки - водитель+организация.
Для каждой группы все записи, попадающие в 30-минутный интервал, считать одной... за её пределами - разными.
Как почистить группу от лишних записей? вероятно, написать нечто вроде
Код: sql
1.
2.
3.
4.
5.
6.
7.
select *
from table copy1
where not exists ( 
  select 1 
  from table copy2
  where timediff(copy1.datetime, copy2.datetime) between '00:00:00' and '00:30:00'
  )


Оно бы и хорошо, если бы не безделица - а что если чел сделал в одну фирму два рейса? скажем, у него идут записи:
10:20:00
10:25:00
10:30:00
10:45:00
10:50:00
10:55:00
Понимаешь? На глаз видно - две группы... а меж записями не более 10 минут, хотя вся серия - более получаса.
А если вот так:
10:20:00
10:25:00
10:40:00
10:45:00
11:00:00
11:05:00
то сколько групп? одна, две или три?

Понимаю, что придирки. Но раз в год и метла стреляет.
...
Рейтинг: 0 / 0
25.01.2014, 15:37:11
    #38537741
retvizan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
По-моему, это как раз тот случай, когда стоит использовать переменные. Обходим таблицу по id_driver, id_organization, registration. Если меняется организация или время между записями более получаса, увеличиваем счетчик. Если смена водителя, сбрасываем счетчик. Потом группировка по водителю и max(счетчик). И никаких исключений.
...
Рейтинг: 0 / 0
25.01.2014, 22:57:05
    #38537935
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
retvizanПо-моему, это как раз тот случай, когда стоит использовать переменные.ПО-моему, это тот случай, когда описанной логике нечего делать на сервере. Она нереляционна. Пусть вертится или на клиенте, или на прокладке (скажем, реализовать скриптами веб-сервера).
...
Рейтинг: 0 / 0
27.01.2014, 13:05:12
    #38538867
Sergey_samara
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
AkinaТэкс...
Понятно, что первый уровень группировки - водитель+организация.
Для каждой группы все записи, попадающие в 30-минутный интервал, считать одной... за её пределами - разными.
Как почистить группу от лишних записей? вероятно, написать нечто вроде
Код: sql
1.
2.
3.
4.
5.
6.
7.
select *
from table copy1
where not exists ( 
  select 1 
  from table copy2
  where timediff(copy1.datetime, copy2.datetime) between '00:00:00' and '00:30:00'
  )




Одно замечание по поводу условия. Такой запрос будет работать очень медленно на приличном кол-ве записей. Правильней как-то так а заодно стоит проверить фирму:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
select *
from table copy1
where not exists ( 
  select 1 
  from table copy2
  where copy2.datetime between copy1.datetime and copy1.datetime + interval 30 minute
    and copy2.org = copy1.org
)
...
Рейтинг: 0 / 0
28.01.2014, 19:58:49
    #38541193
Atletnah
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
retvizanПо-моему, это как раз тот случай, когда стоит использовать переменные. Обходим таблицу по id_driver, id_organization, registration. Если меняется организация или время между записями более получаса, увеличиваем счетчик. Если смена водителя, сбрасываем счетчик. Потом группировка по водителю и max(счетчик). И никаких исключений.

retvizan, спасибо!

Sergey_samara,
Оба запроса выполняются крайне долго.

Сделал следующим образом:

Выбираю водителей.
Обрабатываю на клиенте (пользуюсь Lazarus+MySQL)
Выполняю скрипт для каждого водителя
Код: sql
1.
2.
3.
4.
5.
SET @r_n=NULL, @r_o=NULL, @n=0, @org_n=NULL, @org_o=NULL;
SELECT @org_n:=accounting.organization_id, @r_n:=accounting.registration, 
if((unix_timestamp(@r_n)-unix_timestamp(@r_o)>1800) or (@org_n<>@org_o), @n:=@n+1, @n) as n, 
@r_o:=accounting.registration, @org_o:=accounting.organization_id  
FROM accounting WHERE (registration between :DateStart and  :DateEnd) and accounting.driver_id =:driver_id;



Меняю статус в ProgressBar при смене водителя, чтобы не казалось, что приложение зависло. На все расчеты уходит около 5-7 секунд. Размер таблицы > 60000 записей.

Вроде работает. Может конечно выглядит криво, но работает.
Если у кого есть какие-либо рекомендации или замечания, рад любой критике)
...
Рейтинг: 0 / 0
28.01.2014, 20:34:16
    #38541231
retvizan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
Atletnah,
А за счет чего вы уверены, что проход по таблице идет в нужном порядке?
...
Рейтинг: 0 / 0
28.01.2014, 20:40:51
    #38541238
Atletnah
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
retvizan,

Код: sql
1.
ORDER BY registration ???
...
Рейтинг: 0 / 0
28.01.2014, 21:06:25
    #38541258
retvizan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Выборка с группировкой записей с разницой во времени меньше 30 минут
да
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Выборка с группировкой записей с разницой во времени меньше 30 минут / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]