在一系列操作中查找最后一次停止时间sql

时间:2017-08-08 05:12:25

标签: sql sql-server

有一位播放器会播放视频。用户可以开始或停止视频。

每次用户播放视频时,都会显示video_click_id。我想在结束视频的系列停止中找到第一站的id。如果video_click_id以一站结束,则获取最后一站。如果video_click_id以两次停止结束,则获得第二个最后一站。如果video_click_id以3站结束,则获得第3站。

   id          video_click_id action_timestamp          action
   ----------- ------------- -----------------------   ------
   3           1             2016-05-19 13:59:07.437   play
   4           1             2016-05-19 13:59:13.413   stop
   6           1             2016-05-19 15:59:40.213   stop
   8           2             2016-05-19 16:29:11.950   play
   9           2             2016-05-19 16:29:27.090   stop
   10          2             2016-05-19 16:29:28.000   play
   12          2             2016-05-19 16:29:29.390   stop
   13          3             2016-05-19 20:59:07.437   play
   14          3             2016-05-19 20:59:13.413   stop
   15          3             2016-05-19 20:59:40.213   stop
   26          3             2016-05-19 20:59:40.213   stop
  1. 在这种情况下,video_click_id 1的结果ID将为4.
  2. video_click_id 2的结果ID为12。
  3. video_click_id 3的结果ID为14。
  4. 任何人都可以帮助我吗?我正在使用mssql。

    提前致谢!

4 个答案:

答案 0 :(得分:0)

在下面的查询中,子查询为每个stop记录分配一个行号。然后,外部查询保留每个video_click_id组的第一个停止记录。

SELECT
    t.id,
    t.video_click_id,
    t.action_timestamp,
    t.action
FROM
(
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY video_click_id ORDER BY action_timestamp) rn
    FROM yourTable
    WHERE action = 'stop'
) t
WHERE t.rn = 1

<强>输出:

enter image description here

在这里演示:

Rextester

答案 1 :(得分:0)

您可以使用not exists来检索后跟播放的所有停靠点。然后,您可以使用group by选择后跟播放的最早id停止:

select min(id), video_click_id
from mytable t1
where action = 'stop'
and not exists ( -- subquery ensures that no 'play' occurs after 'stop'
    select 1 from mytable t2
    where t2.video_click_id = t1.video_click_id
    and t2.action = 'play'
    and t2.id > t1.id
) group by video_click_id

答案 2 :(得分:0)

假设 id 是增量式的,您可以使用以下简单查询来获得所需的输出 -

SELECT MAX(id) AS id, video_click_id
FROM
(
    SELECT *
     , LAG(action) OVER(PARTITION BY video_click_id ORDER BY action_timestamp) AS prev_action
    FROM MyTable
) AS p
WHERE action = 'stop' AND prev_action = 'play'
GROUP BY video_click_id;

子查询为每个操作找到上一个操作。我们希望在最后一次“播放”操作后立即执行“停止”操作。因此,选择id的最大值将获得视频实际停止的ID。

SqlFiddle Demo

答案 3 :(得分:0)

嗯,蒂姆的答案对于问题的第一个版本是正确的,但是在编辑问题之后,它需要一个小的调整 - 在派生表中添加一个不存在的诀窍:

SELECT
    t.id,
    t.video_click_id,
    t.action_timestamp,
    t.action
FROM
(
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY video_click_id ORDER BY action_timestamp) rn
    FROM yourTable t0
    WHERE action = 'stop'
    AND NOT EXISTS
    (
        SELECT 1
        FROM yourTable t1
        WHERE t1.video_click_id = t0.video_click_id 
        AND t1.action = 'play'
        AND t1.action_timestamp > t0.action_timestamp
    )
) t
WHERE t.rn = 1;

输出:

id  video_click_id  action_timestamp            action
4   1               2016-05-19 13:59:13.413     stop
12  2               2016-05-19 16:29:29.390     stop
14  3               2016-05-19 20:59:13.413     stop

Rextester link