微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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请记住,这是一个后处理步骤.除非您对其进行子查询,否则您将无法对分析函数的值执行过滤等操作.

原文地址:https://www.jb51.cc/postgresql/191662.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐