我有一张桌子:

CREATE TABLE t_table (
    c_id int4 NOT NULL,
    c_date_called int4 NOT NULL,
    CONSTRAINT t_table_un UNIQUE (c_id, c_date_called)
);

它存储不同的数据快照,数据如下:

INSERT INTO t_table (c_id, c_date_called) 
   VALUES
(1,9),
(2,9),
(3,9),
(4,9),
(5,9),
(1,12),
(2,12),
(3,12),
(5,12),
(1,17),
(3,17)
;

针对这个表,我可以运行一个反连接,比较current快照和一个previous快照:

--EXPLAIN ANALYSE VERBOSE
SELECT prev.*
    FROM t_table AS prev
    LEFT JOIN t_table AS cur ON (prev.c_id = cur.c_id) AND cur.c_date_called = 17
    WHERE prev.c_date_called = 9
        AND cur.c_id IS NULL
        ;

返回我在查找当前c_date_called中不存在的ID时预期的数据:

c_id|c_date_called|
----+-------------+
   2|            9|
   4|            9|

但是,我如何对多个不同的c_date_called应用反联接,收集结果并将它们与current c_date_called进行合并呢?

井.具有反联接的窗口函数..是啊,我需要帮助.

推荐答案

好的,在快照中报告is的完成状态,即具有new id的快照在前一快照中不存在.id removed,即不在next快照中,您不需要anti-join.您无论如何都不会在您的示例中使用它.

首先使用integers定义快照序列并标记当前快照

with snap as (
select distinct c_date_called from t_table),
snap2 as (
select  
  c_date_called,
  row_number() over(order by c_date_called) as snap_idx,
  c_date_called = max(c_date_called) over() is_current
from snap)
select * from snap2;

c_date_called|snap_idx|is_current|
-------------+--------+----------+
            9|       1|false     |
           12|       2|false     |
           17|       3|true      |

然后将此支持信息连接到您的主表,并基于snapshot indexlaglead窗口函数添加两个属性,这两个属性标识给定id的上一个/下一个快照是连续的还是有差距.其中的逻辑应该不言而喻.

with snap as (
select distinct c_date_called from t_table),
snap2 as (
select  
  c_date_called,
  row_number() over(order by c_date_called) as snap_idx,
  c_date_called = max(c_date_called) over() is_current
from snap)
select 
 a.c_id, a.c_date_called, b.snap_idx, b.is_current,
 snap_idx != (1 + lag(snap_idx,1,0) over(partition by a.c_id order by snap_idx)) is_new,
 not (is_current) and snap_idx + 1 !=lead(snap_idx,1,0) over(partition by a.c_id order by snap_idx) is_removed
from t_table a
join snap2 b on a.c_date_called = b.c_date_called
order by 1,3;

c_id|c_date_called|snap_idx|is_current|is_new|is_removed|
----+-------------+--------+----------+------+----------+
   1|            9|       1|false     |false |false     |
   1|           12|       2|false     |false |false     |
   1|           17|       3|true      |false |false     |
   2|            9|       1|false     |false |false     |
   2|           12|       2|false     |false |true      |
   3|            9|       1|false     |false |false     |
   3|           12|       2|false     |false |false     |
   3|           17|       3|true      |false |false     |
   4|            9|       1|false     |false |true      |
   5|            9|       1|false     |false |false     |
   5|           12|       2|false     |false |true      |
   6|           12|       2|false     |true  |false     |
   6|           17|       3|true      |false |false     |

请注意,我添加了在第二个快照中介绍的id 6以演示此用例.

Postgresql相关问答推荐

如何将Postgs SUM结果存储在多个变量中?

Postgres 13.8 -如何在对数据执行窗口操作时返回所有行

为什么32632投影中的几何图形并不完美?

为什么 Postgres 中的 now() 和 now()::timestamp 对于 CET 和 CEST 时区如此错误?

如何在 PostgreSQL 的回归测试中测试 TYPE 发送和接收函数

MERGE 语句的锁定级别

从具有加权行概率的 PostgreSQL 表中 Select 随机行

PostgreSQL 错误:42P01:relation "[Table]" does not exist

如何让 Flask SQLAlchemy 重用数据库连接?

如何从元组列表中 Select 与多列匹配的行?

从局域网访问 PostgreSQL 服务器

Postgres 中的相似函数与 pg_trgm

Postgres NOT IN (null) 没有结果

设置 Phoenix 框架和 Ecto 以使用 UUID:如何插入生成的值?

使用 RPostgreSQL 写入特定模式

Array Push的 Postgres 数组追加和数组长度

SQL:子查询的列太多

PostgreSQL 无法启动:server.key具有组或世界访问权限

PostgreSQL 9.1:如何连接数组中的行而不重复,加入另一个表

pgadmin 错误:no password supplied