【问题标题】:sql window function to detect change in column valuessql窗口函数检测列值的变化
【发布时间】:2016-08-20 00:31:46
【问题描述】:

我想检测此(示例)db 中列值的变化

    WITH events(id, row,event) AS (
    VALUES
    (1,1, 0 )
   ,(1,2, 0 ) 
   ,(1,3, 1 )
   ,(1,4, 0 )
   ,(1,5, 1 )
   ,(2,1, 0 )
   ,(2,2, 1 )
   ,(3,1, 0 )
   ,(3,2, 0 )
   )
   select * from events

我正在寻找的是新列“代码”的代码,该列在之后切换为 1 de 事件列显示 1。在同一 id 内,代码保持 1。 对于这个例子,这个新列将如下所示

    WITH events2(id, row,event, code) AS (
    VALUES
    (1,1, 0, 0 )
   ,(1,2, 0, 0 ) 
   ,(1,3, 1, 0 )
   ,(1,4, 0, 1 ) -- notice the switch here
   ,(1,5, 1, 1 ) -- 
   ,(2,1, 0, 0 )
   ,(2,2, 1, 0 )
   ,(3,1, 0, 0 )
   ,(3,2, 0, 0 )
   )
   select * from events2

我有预感,答案将与这个问题的答案有关:PostgreSQL window function: partition by comparison

不知怎的,我自己也弄不明白..

彼得

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    通过标量子查询进行 COALESCE:

    WITH events(id, zrow, zevent) AS (
        VALUES
        (1,1, 0 ) ,(1,2, 0 ) ,(1,3, 1 ) ,(1,4, 0 ) ,(1,5, 1 )
       ,(2,1, 0 ) ,(2,2, 1 )
       ,(3,1, 0 ) ,(3,2, 0 )
       )
    SELECT id, zrow, zevent
            , COALESCE((SELECT 1 FROM events ex WHERE ex.id = ev.id AND ex.zrow < ev.zrow AND ex.zevent> 0),0) AS oevent
     FROM events ev
            ;
    

    或者,通过将布尔 EXISTS() 类型转换为 INTEGER 来避免 COALESCE():

    WITH events(id, zrow,event) AS (
        VALUES
        (1,1, 0 ) ,(1,2, 0 ) ,(1,3, 1 ) ,(1,4, 0 ) ,(1,5, 1 )
       ,(2,1, 0 ) ,(2,2, 1 )
       ,(3,1, 0 ) ,(3,2, 0 )
       )
    SELECT id, zrow, event
            , EXISTS(SELECT 1 FROM events ex WHERE ex.id = ev.id AND ex.zrow < ev.zrow AND ex.event> 0)::integer AS oevent
    FROM events ev
            ;
    

    在同一组()内的先前记录中查找 MAX() 值:

    WITH events(id, zrow,event) AS (
        VALUES
        (1,1, 0 ) ,(1,2, 0 ) ,(1,3, 1 ) ,(1,4, 0 ) ,(1,5, 1 )
       ,(2,1, 0 ) ,(2,2, 1 )
       ,(3,1, 0 ) ,(3,2, 0 )
       )
    , drag AS (
            SELECT id, zrow, event, MAX(event)
                    OVER (PARTITION BY id
                            ORDER BY zrow
                            ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
                            ) AS lagged
            FROM events ev
            )
    SELECT id, zrow, event
            , COALESCE(lagged,0) AS oevent
            FROM drag dr
            ;
    

    同样没有额外的 CTE:

    WITH events(id, zrow,event) AS (
        VALUES
        (1,1, 0 ) ,(1,2, 0 ) ,(1,3, 1 ) ,(1,4, 0 ) ,(1,5, 1 )
       ,(2,1, 0 ) ,(2,2, 1 )
       ,(3,1, 0 ) ,(3,2, 0 )
       )
    SELECT id, zrow, event, COALESCE(MAX(event) OVER (PARTITION BY id
                                                    ORDER BY zrow
                                                    ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
                                    ),0) AS lagged
            FROM events ev
            ;
    

    另一种执行自联接的方法是使用递归查询。

    【讨论】:

      猜你喜欢
      • 2023-04-05
      • 2012-05-31
      • 2012-05-29
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 2015-02-13
      • 1970-01-01
      相关资源
      最近更新 更多