Выберите только наименее уникальное значение из 2 последовательных строк в группе - PullRequest
3 голосов
/ 27 марта 2019

У меня есть следующая таблица, и я хотел бы сгенерировать данные, описанные ниже. «ХОЧУ» Я перепробовал несколько аналитических функций SQL (rank () over), но я всегда сталкиваюсь с препятствиями.Я буду признателен за любые идеи в отношении решения этой задачи

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

Ответы [ 3 ]

3 голосов
/ 27 марта 2019

Вы можете использовать Табибитозан , чтобы получить группы для каждого идентификатора на основе последовательных строк:

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

db <> fiddle demo .

(Что, я думаю, в принципе та же идея, что и у Пондера ...)

Это также будет работать, если они на самом деле являются датами, а не строками - db <> fiddle . (Как и Ponder's, благодаря арифметике даты!)

3 голосов
/ 27 марта 2019

Этот запрос дал мне хотел строк:

select id, val1, val2, val3, min(dt_val) min_dt
  from (select t.*, 
               dt_val - row_number() over (partition by val1, val2, val3 order by dt_val) diff 
          from tablea t)
  group by id, val1, val2, val3, diff
  order by id, min(dt_val)

демо

1 голос
/ 27 марта 2019
-- 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.
...