2015-11-26 40 views
0

如何在Oracle中使用SQL检索每个第一列A,B,以防B列更改A所排序的值?Oracle SQL:获取每个复杂组/分区的第一个值

假设我有日期和值表:

DATE;VALUE 
01-2015;1 
02-2015;1 
01-2016;2 
01-2016;2 
01-2017:1 

所以我现在想,是一旦值改变每个第一线(基于某些orderning这里DATE)所以从这个组我想:

DATE;VALUE 
01-2015;1 
01-2016;2 
01-2017:1 

现在我不能使用简单的GROUP BY值,因为该值会(2015年和2017年在这种情况下1)再次翻转回来,MIN(DATECOL)GROUP BY VALUECOL不会报告这个2017年。

所以我一直在寻找进入分析功能类似:

SELECT FIRST_VALUE(DATECOL),FIRST_VALUE(VALUECOL) OVER (PARTITION BY 
VALUECOL ORDER BY DATECOL) FROM DATATABLE 

但我不能得到这个工作!

回答

2

Tabibtosan让一切变得简单:

with table1 as (select to_date('01/01/2015', 'dd/mm/yyyy') dt, 1 val from dual union all 
       select to_date('01/02/2015', 'dd/mm/yyyy') dt, 1 val from dual union all 
       select to_date('01/01/2016', 'dd/mm/yyyy') dt, 2 val from dual union all 
       select to_date('01/01/2016', 'dd/mm/yyyy') dt, 2 val from dual union all 
       select to_date('01/01/2017', 'dd/mm/yyyy') dt, 1 val from dual) 
-- end of mimicking a table "table1" with data in it. See sql below: 
select min(dt) dt, 
     val 
from (select dt, 
       val, 
       dense_rank() over (order by dt) 
       - dense_rank() over (partition by val order by dt) grp 
     from table1) 
group by val, 
     grp; 

DT    VAL 
---------- ---------- 
01/01/2015   1 
01/01/2016   2 
01/01/2017   1 
+0

真棒。谢谢 – robert

0

我觉得LAG()是相应的功能,与其他一些逻辑一起:

select t.* 
from (select t.*, lag(value) over (order by date) as prev_value 
     from datatable t 
    ) t 
where prev_value is null or prev_value <> value; 

与您的数据的唯一问题是,行不是唯一的。这可能会导致问题,因为数据库中的排序不稳定(也就是说,两行可以按任一顺序排列)。希望在您的实际数据中,日期是唯一的,或者您有另外一个ID,您可以将其添加到order by以确保排序稳定。这样做的

一种蛮力的方法是:

with dt as (
     select dt.*, rownum as rn 
     from datatable dt 
    ) 
select t.* 
from (select dt.*, lag(value) over (order by date, rn) as prev_value 
     from datatable dt 
    ) t 
where prev_value is null or prev_value <> value; 
相关问题