在多列上使用 lag() (间隙和岛屿问题)

Tom*_*yer 4 postgresql window-functions

我有一个问题正在尝试解决,我需要使用前 7 列作为基础来消除表中重复的连续行,以确定它是否重复。数据如下:

textColA|textColB|textColC|textColD|textColE|numCol1|numCol2|eventNum
--------+--------+--------+--------+--------+-------+-------+--------
    x   |    y   |    z   |  foo   |  bar   |  1    | 2     | 1
    x   |    y   |    z   |  foo   |  bar   |  1    | 2     | 2 
    x   |    y   |    z   |  foo   |  bar   |  1.1  | 2     | 3
    x   |    y   |    z   |  foo   |  bar   |  1.1  | 2     | 4
    x   |    y   |    z   |  foo   |  bar   |  1    | 2     | 5
    x   |    y   |    z   |  foo   |  bar   |  1    | 2     | 6

Run Code Online (Sandbox Code Playgroud)

按照显示的顺序显示这些数据,我想保留 eventNum 1,3 和 5 - 事件 5,因为尽管它与 1 和 2 相同,但后面跟着 4,这是不一样的。

我有代码使用游标循环遍历每一行并进行比较,但是虽然这适用于具有 1、2 甚至 1000 万行的表,但在我需要的 300-400m 行表上可能会出现问题来处理。

我使用 lag() 函数查看了不同的解决方案,但我看到的示例仅处理一列,而且我似乎无法获得使用多列的正确语法。

任何帮助表示赞赏。

Col*_*art 5

lag()仅适用于单个列,因此您需要为每个滞后值定义一个新的“列”。您可以使用公共 Window 子句,以便查询规划器清楚地知道它只需要对行进行一次排序 - 尽管我认为 Postgres 也可以自行确定这一点 - 但它也可以节省打字。

之后,只需比较“滞后”值,看看它们是否有任何不同。is distinct from在这里很方便,因为第一个“滞后”值都是null,因此它们与第一行的值不同,因此第一行将包含在输出中。

把它们放在一起,它的工作原理如下:

select textColA, textColB, textColC, textColD, textColE, numCol1, numCol2, eventNum
from (
  select
    l.*,
    lag(textColA) over w as lagTextColA,
    lag(textColB) over w as lagTextColB,
    lag(textColC) over w as lagTextColC,
    lag(textColD) over w as lagTextColD,
    lag(textColE) over w as lagTextColE,
    lag(numCol1) over w as lagNumCol1,
    lag(numCol2) over w as lagNumCol2
  from lagger l
  window w as (order by textColA, textColB, textColC, textColD, textColE, eventNum)
) x
where
   textColA is distinct from lagTextColA
or textColB is distinct from lagTextColB
or textColC is distinct from lagTextColC
or textColD is distinct from lagTextColD
or textColE is distinct from lagTextColE
or numCol1 is distinct from lagNumCol1
or numCol2 is distinct from lagNumCol2
;
Run Code Online (Sandbox Code Playgroud)

完整的小提琴在这里:https://dbfiddle.uk/? rdbms=postgres_11&fiddle=2e11af872a47bd75a20c64f87e7a6cd6(注意,在小提琴中我忘记了 Window 子句中的其他列)