2010-12-11 58 views
4

列的变化查询,我有表,其中包括我的产品表的日志这样的:这说明从表

process_time    product_id product_type_id 
04.07.2009 14:08:43  5   4 
05.07.2009 15:08:43  5   4 
06.07.2009 16:08:43  5   6 
07.07.2009 16:08:43  5   6 
08.07.2009 17:08:43  5   4 
08.07.2009 18:08:43  5   4 

我想编写一个查询,显示product_type_id的变化。对于上面的示例,我的查询结果应如下所示:

process_time    product_id product_type_id 
04.07.2009 14:08:43  5   4 
06.07.2009 16:08:43  5   6 
08.07.2009 17:08:43  5   4 

如何编写此查询?

回答

4

像这样:

select * from 
(select process_time, product_id, product_type_id 
,lag(product_type_id) over (partition by product_id order by process_time) as prevrow 
,lead(product_type_id) over (partition by product_id order by process_time) as nextrow 
from products) 
where nextrow <> product_type_id or nextrow is null; 

对于所有谁愿意看到这是如何工作:

create table products (process_time timestamp, product_id number, product_type_id number); 

insert into products values (to_date('2009-07-04 14:08:43','YYYY-MM-DD hh24:mi:ss'),5,4); 
insert into products values (to_date('2009-07-05 15:08:43','YYYY-MM-DD hh24:mi:ss'),5,4); 
insert into products values (to_date('2009-07-06 16:08:43','YYYY-MM-DD hh24:mi:ss'),5,6); 
insert into products values (to_date('2009-07-07 16:08:43','YYYY-MM-DD hh24:mi:ss'),5,6); 
insert into products values (to_date('2009-07-08 17:08:43','YYYY-MM-DD hh24:mi:ss'),5,4); 
insert into products values (to_date('2009-07-08 18:08:43','YYYY-MM-DD hh24:mi:ss'),5,4); 

commit; 

select process_time, product_id, product_type_id 
,lag(product_type_id) over (partition by product_id order by process_time) as prevrow 
,lead(product_type_id) over (partition by product_id order by process_time) as nextrow 
from products 
order by process_time; 

select * from 
(select process_time, product_id, product_type_id 
,lag(product_type_id) over (partition by product_id order by process_time) as prevrow 
,lead(product_type_id) over (partition by product_id order by process_time) as nextrow 
from products) 
where nextrow <> product_type_id or nextrow is null; 

commit; 

drop table products; 

执行的,我们得到:

Table created. 
1 row created. 
1 row created. 
1 row created. 
1 row created. 
1 row created. 
1 row created. 
Commit complete. 

PROCESS_TIME     PRODUCT_ID PRODUCT_TYPE_ID PREVROW NEXTROW 
------------------------------- ---------- --------------- ---------- ---------- 
04-JUL-09 02.08.43.000000 PM    5    4      4 
05-JUL-09 03.08.43.000000 PM    5    4   4   6 
06-JUL-09 04.08.43.000000 PM    5    6   4   6 
07-JUL-09 04.08.43.000000 PM    5    6   6   4 
08-JUL-09 05.08.43.000000 PM    5    4   6   4 
08-JUL-09 06.08.43.000000 PM    5    4   4   


6 rows selected. 

PROCESS_TIME     PRODUCT_ID PRODUCT_TYPE_ID PREVROW NEXTROW 
------------------------------- ---------- --------------- ---------- ---------- 
05-JUL-09 03.08.43.000000 PM    5    4   4   6 
07-JUL-09 04.08.43.000000 PM    5    6   6   4 
08-JUL-09 06.08.43.000000 PM    5    4   4   


3 rows selected. 
Commit complete. 
Table dropped. 
+0

非常感谢朋友。 – mavera 2010-12-12 14:05:26

+0

这可能救了我几个小时的工作:) – chris 2011-08-19 18:52:50

2

使用LAG analytic function找到前值product_type_id列的值。如果当前值和先前值不同,那应该是你想要的那一行。对于第一行,LAG函数将返回null,因为没有先前的行,所以您还需要对此进行测试。

select 
    process_time, 
    product_id, 
    product_type_id, 
from (
    select 
    process_time, 
    product_id, 
    product_type_id, 
    lag(product_type_id) over (order by process_time) as prior_product_type_id 
    from the_table 
) 
where 
    (prior_product_type_id <> product_type_id or prior_product_type_id is null) 
+0

感谢您的回复。你和Jurgen的解决方案帮助了我。 – mavera 2010-12-12 14:06:07