Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 仅选择一个组中两个连续行的最小唯一值_Sql_Oracle_Gaps And Islands - Fatal编程技术网

Sql 仅选择一个组中两个连续行的最小唯一值

Sql 仅选择一个组中两个连续行的最小唯一值,sql,oracle,gaps-and-islands,Sql,Oracle,Gaps And Islands,我有下表,我想生成下面描述的数据“想要”我尝试了几个SQL分析函数(rank()),但我似乎总是遇到障碍。对于解决此任务的任何见解,我将不胜感激 CREATE TABLE TABLEA ( id VARCHAR(2) , val1 VARCHAR(2), val2 VARCHAR(2), val3 VARCHAR(2), dt_val VARCHAR(8) ) ; -- --data INSERT INTO TABLEA (id, val1, val2, val3, dt_val) VAL

我有下表,我想生成下面描述的数据“想要”我尝试了几个SQL分析函数(rank()),但我似乎总是遇到障碍。对于解决此任务的任何见解,我将不胜感激

CREATE TABLE TABLEA (
id VARCHAR(2) ,
val1  VARCHAR(2),
val2 VARCHAR(2),
val3 VARCHAR(2),
dt_val VARCHAR(8)
)
;

-- --data
INSERT INTO TABLEA
(id, val1, val2, val3,  dt_val)
VALUES
('1', '2', '3', '4', '20151011'),
('1', '2', '', '4', '20151012'),
('1', '2', '3', '4', '20151013'),
('2', '4', '3', '4', '20151101'),
('2', '4', '3', '4', '20151102'),
('2', '4', '', '', '20151103'),
('2', '4', '3', '4', '20151104'),
('3', '4', '3', '4', '20151110'),
('4', '4', '3', '4', '20151110'),
('4', '4', '3', '4', '20151111'),
('4', '4', '', '4', '20151112'),
('4', '4', '', '4', '20151113'),
('5', '4', '3', '4', '20151111'),
('5', '4', '3', '4', '20151112'),
('5', '4', '3', '4', '20151113'),
('5', '4', '3', '4', '20151114'),
;
想要 我想要下面的结果。如果两个连续行相同,我想选择最小值(dt_val)

    Id     val1   val2   val3    dt_val 
  ------ ------ ------ ------    ----------------
    1      2        3         4         20151011
    1      2       (null)     4         20151012
    1      2       3          4         20151013
    2      4       3          4         20151101
    2      4       (null)   (null)      20151103
    2      4       3          4         20151104
    3      4       3          4         20151110
    4      4       3          4         20151110
    4      4       (null)     4         20151112
    5      4       3          4         20151111
此查询为我提供了想要的行:

您可以根据连续行获取每个ID的组:

select a.*,
  row_number() over (partition by id order by dt_val)
    - row_number() over (partition by id, val1, val2, val3 order by dt_val) as grp
from tablea a
order by id, dt_val;
然后应用聚合函数:

select id, val1, val2, val3, min(dt_val) as dt_val
from (
  select a.*,
    row_number() over (partition by id order by dt_val)
      - row_number() over (partition by id, val1, val2, val3 order by dt_val) as grp
  from tablea a
)
group by id, val1, val2, val3, grp
order by id, dt_val;

ID VAL1 VAL2 VAL3 DT_VAL  
-- ---- ---- ---- --------
1  2    3    4    20151011
1  2         4    20151012
1  2    3    4    20151013
2  4    3    4    20151101
2  4              20151103
2  4    3    4    20151104
3  4    3    4    20151110
4  4    3    4    20151110
4  4         4    20151112
5  4    3    4    20151111

(我想这基本上与Pounder的想法相同…)

如果它们实际上是日期而不是字符串-,这也会起作用。(正如Pounder的一样,多亏了date算术!)

select id, val1, val2, val3, min(dt_val) as dt_val
from (
  select a.*,
    row_number() over (partition by id order by dt_val)
      - row_number() over (partition by id, val1, val2, val3 order by dt_val) as grp
  from tablea a
)
group by id, val1, val2, val3, grp
order by id, dt_val;

ID VAL1 VAL2 VAL3 DT_VAL  
-- ---- ---- ---- --------
1  2    3    4    20151011
1  2         4    20151012
1  2    3    4    20151013
2  4    3    4    20151101
2  4              20151103
2  4    3    4    20151104
3  4    3    4    20151110
4  4    3    4    20151110
4  4         4    20151112
5  4    3    4    20151111
-- Oracle 12c+
with s (id, val1, val2, val3,  dt_val) as (
select 1, '2', '3', '4', '20151011' from dual union all
select 1, '2', '' , '4', '20151012' from dual union all
select 1, '2', '3', '4', '20151013' from dual union all
select 2, '4', '3', '4', '20151101' from dual union all
select 2, '4', '3', '4', '20151102' from dual union all
select 2, '4', '' , '' , '20151103' from dual union all
select 2, '4', '3', '4', '20151104' from dual union all
select 3, '4', '3', '4', '20151110' from dual union all
select 4, '4', '3', '4', '20151110' from dual union all
select 4, '4', '3', '4', '20151111' from dual union all
select 4, '4', '' , '4', '20151112' from dual union all
select 4, '4', '' , '4', '20151113' from dual union all
select 5, '4', '3', '4', '20151111' from dual union all
select 5, '4', '3', '4', '20151112' from dual union all
select 5, '4', '3', '4', '20151113' from dual union all
select 5, '4', '3', '4', '20151114' from dual)
select *
from s
match_recognize (
order by id
measures 
  v.id            as id, 
  v.val1          as val1, 
  v.val2          as val2, 
  v.val3          as val3,
  first(v.dt_val) as dt_val 
pattern (v+)
define v as 
     decode(v.id  , first(id  ), 0) = 0 and
     decode(v.val1, first(val1), 0) = 0 and
     decode(v.val2, first(val2), 0) = 0 and
     decode(v.val3, first(val3), 0) = 0
);

 ID VAL1 VAL2 VAL3 DT_VAL  
--- ---- ---- ---- --------
  1 2    3    4    20151011
  1 2         4    20151012
  1 2    3    4    20151013
  2 4    3    4    20151101
  2 4              20151103
  2 4    3    4    20151104
  3 4    3    4    20151110
  4 4    3    4    20151110
  4 4         4    20151112
  5 4    3    4    20151111

    10 rows selected.