SQL 获取最后一次数字被设置为 1

SQL get the last time number was set to 1

我有一个类似于下面的 sql table。我想获取它最后一次从 0 更改为 1 以及最后一次更改回 0(下面突出显示的示例 ID)。

我试过的是:

select * from Table t1 join Table t2 on t1.id = t2.id join Table t3 on t1.id = t3.id 
where t1.flag = 1 and t2.flag = 0 and t3.flag 
group by t1.id
having min(t1.createdtime) between max(t2.createdtime) and min(t3.createdtime)

对于这个数据集,可以用lag()把上一行的flag带进来,作为过滤条件,然后聚合:

select 
    id,
    max(createdtime) createdtime,
    flag
from (
    select 
        t.*,
        lag(flag) over(partition by id order by createdtime) lagflag
    from mytable t
) t
where (flag = 0 and lagflag = 1) or (flag = 1 and lagflag = 0)
group by id, flag

您可以使用lag() 获取最近的标志。所以你可以过滤变化,即当(当前)标志和最近的标志根据需要相关时。要仅获取最新的更改,您可以按 row_number().

进行过滤
SELECT z.id,
       z.createdtime,
       z.flag
       FROM (SELECT y.id,
                    y.createdtime,
                    y.flag FROM (SELECT x.id,
                                        x.createdtime,
                                        x.flag,
                                        row_number() OVER (PARTITION BY x.id
                                                           ORDER BY x.createdtime DESC) rn
                                        FROM (SELECT t.id,
                                                     t.createdtime,
                                                     t.flag,
                                                     lag(t.flag) OVER (PARTITION BY t.id
                                                                       ORDER BY createdtime) recentflag
                                                     FROM elbat t) x
                                                     WHERE x.flag = 0
                                                           AND x.recentflag = 1) y
                    WHERE y.rn = 1
             UNION ALL
             SELECT y.id,
                    y.createdtime,
                    y.flag FROM (SELECT x.id,
                                        x.createdtime,
                                        x.flag,
                                        row_number() OVER (PARTITION BY x.id
                                                           ORDER BY x.createdtime DESC) rn
                                        FROM (SELECT t.id,
                                                     t.createdtime,
                                                     t.flag,
                                                     lag(t.flag) OVER (PARTITION BY t.id
                                                                       ORDER BY createdtime) recentflag
                                                     FROM elbat t) x
                                                     WHERE x.flag = 1
                                                           AND x.recentflag = 0) y
                    WHERE y.rn = 1) z
       ORDER BY z.createdtime DESC;

CTE 中使用 lag() 获取每一行的前一个标志,然后 NOT EXISTS:

with cte as(
    select *, lag(flag) over(partition by id order by createdtime) prevflag
    from tablename 
) 
select c.id, c.createdtime, c.flag
from cte c
where c.flag <> c.prevflag 
and not exists (
  select 1 from cte
  where id = c.id and flag = c.flag and prevflag = c.prevflag and createdtime > c.createdtime
)
order by c.createdtime

或:

with cte as(
    select *, lag(flag) over(partition by id order by createdtime) prevflag
    from tablename 
)
select id, max(createdtime) createdtime, flag
from cte
where flag <> prevflag 
group by id, flag
order by createdtime

参见demo
结果:

> id | createdtime         | flag
> -: | :------------------ | ---:
>  5 | 2019-11-02 14:30:00 |    1
>  5 | 2020-08-01 14:30:00 |    0