2015-01-09 2 views
0

Я пытаюсь выяснить, «сколько уникальных сообщений было отправлено человеку на определенной лодке в течение определенного периода времени и каковы минимальные дни между этими текстами» и отображать включая счетчик.Группа по идентификаторам и TIMESTAMPDIFF один столбец в одной таблице

Лицо представлено 'id', лодкой 'id2' и сообщением 'text'.

CREATE TABLE `stacktable` (
`timestamp` DATETIME NOT NULL, 
`id` VARCHAR(15) NOT NULL, 
`id2` VARCHAR(3) NULL DEFAULT NULL, 
`text` VARCHAR(255) NULL DEFAULT NULL, 
`id3` INT(10) NOT NULL AUTO_INCREMENT, 
PRIMARY KEY (`id3`) 
); 

insert into stacktable (timestamp,id,id2,text) VALUES 
('2015-01-01 00:00:01',1,10,'ABC'), 
('2015-01-01 00:00:01',2,11,'ABC'), 
('2015-01-01 00:00:01',3,12,'ABC'), 
('2015-01-01 00:00:02',3,12,'ABC'), 
('2015-01-01 00:00:02',1,10,'ABC'), 
('2015-01-04 00:00:01',1,10,'ABC'), 
('2015-01-04 00:00:01',1,10,'BCD'), 
('2015-01-04 00:00:01',2,11,'ABC'), 
('2015-01-04 00:00:01',2,11,'BCD'), 
('2015-01-04 00:00:01',3,12,'ABC'), 
('2015-01-04 00:00:01',3,12,'BCD'), 
('2015-01-04 00:00:01',3,13,'CDE'), 
('2015-01-07 00:00:01',2,11,'BCD'), 
('2015-01-07 00:00:01',3,12,'BCD'), 
('2015-01-07 00:00:01',3,13,'CDE'), 
('2015-01-07 00:00:01',3,13,'DEF'), 
('2015-01-08 00:00:01',3,12,'ABC'), 
('2015-01-08 00:00:01',4,14,'EFG'), 
('2015-01-09 00:00:01',4,14,'EFG'), 
('2015-01-09 00:00:02',4,15,'FGH'), 
('2015-01-10 00:00:01',4,14,'EFG'), 
('2015-01-10 00:00:01',4,14,'FGH'), 
('2015-01-10 00:00:01',4,15,'FGH'), 
('2015-01-11 00:00:01',4,14,'EFG'), 
('2015-01-15 00:00:01',4,14,'EFG'); 

Чтобы показать, что я пытаюсь достичь:

select * from stacktable where id = 1 

timestamp   id id2 text id3  
2015-01-01 00:00:01 1 10 ABC 1 First entry for id+id2+text (ABC) 
2015-01-01 00:00:02 1 10 ABC 5 Second entry for same keys id+id2+text 1 second later 
2015-01-04 00:00:01 1 10 ABC 6 Third entry for same keys id+id2+text 2 days later 
2015-01-04 00:00:01 1 10 BCD 7 First entry for id+id2+text (BCD) 

Я только хочу, чтобы подсчитать количество записей, что имеет «такой же идентификатор, ID2 и текст в течение 2-х дней», но и показать «минимальный интервал между днями».

Выход я хочу от этого был бы:

id id2 text count(*) mindiffdatebetweenhits 
------------------------------------------- 
1 10 ABC 3  0      count id3s 1,5 and 6, minimumdaydiff is between id3 1 and 5 = 0 days 
3 12 ABC 3  0      count id3s 3,4 and 10, minimumdaydiff is between id3 3 and 4 = 0 days 
4 14 EFG 4  1      count id3s 18,19,21 and 24, minimumdaydiff is equal between all hits = 1 day 
4 15 FGH 2  0      count id3s 20 and 23, minimumdaydiff is between id3 20 and 23 = 0 days 

Как я могу получить желаемый результат?

+0

Вы уверены, что это будет ваш выход? Причина разницы между id3 = 6 и 1 составляет более 2 дней. –

+0

Я хочу, чтобы он подсчитал 3 для id = 1 (id3 1,5,6). Это происходит потому, что id3 1 и id3 5 <= 2 дня и id3 5 и id3 6 <= 2. SELECT TIMESTAMPDIFF (день, '2015-01-01 00:00:02', '2015-01-04 00:00: 01 ') from dual = 2 - я хочу «проверить для тех, у кого одинаковый идентификатор, id2, текст в течение 2 дней с момента последнего попадания» –

+0

записи 3 и 4 имеют дату 2015-01-01 и запись 10, 2015-01-04 , Итак, более двух дней. Но вы хотите считать 3 записи. Не похоже, что «в течение 2 дней с момента последнего попадания» – koriander

ответ

1

Это должно сделать это, предполагая, что последовательности только один ряд, должны быть отброшены:

select id, id2, text, seq, count(id) as total, min(diff) as mindiff 
from (
     select t1.row, t2.row row2, t1.id, t1.id2, t1.text, t1.id3, 
      TIMESTAMPDIFF(DAY, t1.timestamp, t2.timestamp) as diff, 
      IF (TIMESTAMPDIFF(DAY, t1.timestamp, t2.timestamp) > 2, @seq * (1 and @seq := @seq +1), @seq) as seq 
     from (select (@row := @row + 1) as row, id, id2, text, id3, timestamp 
      from (select id, id2, text, id3, timestamp 
        from  stacktable 
        order by id, id2, text) sorted, 
        (select @row := 0) setup) t1 
      left join (select (@row2 := @row2 + 1) as row, id, id2, text, id3, timestamp 
         from (select id, id2, text, id3, timestamp 
          from stacktable 
          order by id, id2, text) sorted, 
          (select @row2 := 0) setup) t2 
      on (t1.id = t2.id and t1.id2 = t2.id2 and t1.text=t2.text and t1.row = t2.row - 1), 
      (select @seq := 1) setup_sequence 
    ) t3 
group by id, id2, text, seq 
having total > 1 

Для облегчения чтения, запрос использует тот же раз подзапрос эвакуаторы, t1 и t2, и все это делает своего рода а затем номер строки таблицы:

select (@row := @row + 1) as row, id, id2, text, id3, timestamp 
from (select id, id2, text, id3, timestamp 
     from  stacktable 
     order by id, id2, text) sorted, 
    (select @row := 0) setup 

См fiddle. Обратите внимание, что счетчик последовательности действительно не является уникальным для всех последовательностей. Это не ошибка. Он уникален только между последовательностями одного и того же id, id2, текста.

Обновление счетчика последовательностей несколько сложно: @seq * (1 и @seq: = @seq +1). Он полагается на первую настройку @seq для умножения перед обновлением. Я не уверен, что это детерминированные или последовательные двигатели. Однако запрос можно также изменить, чтобы избежать его, присоединив записи t1 к предыдущей записи вместо следующей записи (в t2). (не проверено)

+0

Какие индексы вы бы порекомендовали для запроса выше? Это становится довольно тяжелым со всеми из них (на столе с ~ 2 миллионами записей –

+0

попробуйте составной индекс для id, id2, text (в этом порядке). – koriander

Смежные вопросы