假设我们有一张桌子:
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;
这就是我用分析方法做的事情:
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请记住,这是一个后处理步骤.除非您对其进行子查询,否则您将无法对分析函数的值执行过滤等操作.