4

У меня есть таблица с двумя столбцами, как:граф равно, последовательные значения в упорядоченном наборе строк

CREATE TABLE actions (
    action_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    "action" text NOT NULL 
); 

и следующие данные в нем:

 action_time   | action 
----------------------------+-------- 
2016-12-30 14:12:33.353269 | a 
2016-12-30 14:12:38.536818 | b 
2016-12-30 14:12:43.305001 | a 
2016-12-30 14:12:49.432981 | a 
2016-12-30 14:12:53.536397 | b 
2016-12-30 14:12:57.449101 | b 
2016-12-30 14:13:01.592785 | a 
2016-12-30 14:13:06.192907 | b 
2016-12-30 14:13:11.249181 | b 
2016-12-30 14:13:13.690897 | b 
(10 rows) 

Вы можете полагать, что нет дубликатов значения в столбце action_time.

Как я могу подсчитать количество одинаковых действий в строке, которые были сделаны начиная с последнего действия?

Ограничений по количеству одинаковых действий в строке нет, и любое действие может быть последним. Кроме того, нет ограничений на разнообразие различных действий: я использовал только два, чтобы упростить данные примера.

Для этого примера данных я ожидаю, что результатом будет 3. Это связано с тем, что последнее действие было «b», и оно произошло 3 раза подряд.

Я думаю, что решение может быть достигнуто путем объединения оконных функций и предложения WITH RECURSIVE, но я не знаю, как это сделать.

ответ

0

Это должно быть сделано.

SELECT COUNT(*) 
FROM actions 
WHERE action_time > (
SELECT action_time 
    FROM actions 
    WHERE action <> (SELECT action FROM actions ORDER BY action_time DESC LIMIT 1) 
ORDER BY action_time DESC LIMIT 1); 

Внутренний запрос Наиболее

SELECT action FROM actions ORDER BY action_time DESC LIMIT 1 

определяет последнее действие.

Запрос

SELECT action_time 
    FROM actions 
    WHERE action <> (SELECT action FROM actions ORDER BY action_time DESC LIMIT 1) 
ORDER BY action_time DESC LIMIT 1 

находит последнюю строку с другим действием.

Самый внешний запрос находит все строки после этой строки.

+0

Работы БОЛЬШОЕ! Большое спасибо. Вы спасли мой день :-) –

0

Я добавил немного поворота к классическому решению зазоров и островов.
Обратите внимание, что функции ROW_NUMBER используют нисходящий ORDER BY.

select count(*) 

from (select 

      action 
      ,row_number() over (     order by action_time desc) as rn 
      ,row_number() over (partition by action order by action_time desc) as rn_action 

     from mytab 
     ) t 

group by action 
     ,rn - rn_action 

having min(rn) = 1 
+0

Это также работает! Благодаря! –

0

Это приходит на ум:

select count(*) 
from t cross join 
    (select t2.action 
     from t t2 
     order by action_time desc 
     limit 1 
    ) last 
where t.action_time >= (select max(t2.action_time) 
         from t t2 
         where t2.action <> last.action 
         ); 

Это должно быть в состоянии воспользоваться индексами на (action_time, action).

+0

Запрос возвращает 4, но должен возвращать 3 :-( –

+0

. Тогда вы использовали бы '>' вместо '> ='. –

0

Улучшенное решение

select count(*) 

from (select 

      action 
      ,row_number() over (     order by action_time desc) as rn 
      ,row_number() over (partition by action order by action_time desc) as rn_action 

     from mytab 
     ) t 

where rn = rn_action 
+0

Он работает. Спасибо чувак. –