PostgreSQL – 列值已更改 – 选择查询优化

假设我们有一张桌子:
CREATE TABLE p
(
   id serial NOT NULL,val boolean NOT NULL,PRIMARY KEY (id)
);

填充了一些行:

insert into p (val)
values (true),(false),(true),(false);
ID  VAL
1   1
2   0
3   0
4   1
5   1
6   1
7   0

我想确定何时更改了值.所以我的查询结果应该是:

ID  VAL
2   0
4   1
7   0

我有一个连接和子查询解决方案:

select min(id) id,val from
(
  select p1.id,p1.val,max(p2.id) last_prev
  from p p1
  join p p2
    on p2.id < p1.id and p2.val != p1.val
  group by p1.id,p1.val
) tmp
group by val,last_prev
order by id;

但它的效率非常低,对于有很多行的表来说效果会非常慢.
我相信使用Postgresql窗口函数可以提供更有效的解决方案吗?

SQL Fiddle

这就是我用分析方法做的事情:
SELECT id,val
  FROM ( SELECT id,val,LAG(val) OVER (ORDER BY id) AS prev_val
       FROM p ) x
  WHERE val <> COALESCE(prev_val,val)
  ORDER BY id

更新(一些解释):

分析函数用作后处理步骤.查询结果分为分组(分区依据),分析函数应用于分组的上下文中.

在这种情况下,查询是从p的选择.正在应用的分析函数是LAG.由于没有partition by子句,因此只有一个分组:整个结果集.此分组按ID排序. LAG使用指定的顺序返回分组中上一行的值.结果是每行都有一个附加列(别名prev_val),它是前一行的val.那是子查询.

然后我们查找val与前一行的val(prev_val)不匹配的行. COALESCE处理第一行的特殊情况,它没有以前的值.

分析函数起初可能看起来有点奇怪,但是对分析函数搜索会发现很多例子都在讨论它们的工作原理.例如:http://www.cs.utexas.edu/~cannata/dbms/Analytic%20Functions%20in%20Oracle%208i%20and%209i.htm请记住,这是一个后处理步骤.除非您对其进行子查询,否则您将无法对分析函数的值执行过滤等操作.

相关文章

项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果...
本文小编为大家详细介绍“怎么查看PostgreSQL数据库中所有表...
错误现象问题原因这是在远程连接时pg_hba.conf文件没有配置正...
因本地资源有限,在公共测试环境搭建了PGsql环境,从数据库本...
wamp 环境 这个提示就是说你的版本低于10了。 先打印ph...
psycopg2.OperationalError: SSL SYSCALL error: EOF detect...