Как создать VIEW на основе таблицы не учитывая дубликатов записей?

Есть таблица ATEST с данными:

create table ATEST (
    id number (9),
    data1 varchar2 (255))

insert into atest values (1, 100);
insert into atest values (1, 100);
insert into atest values (2, 200);
insert into atest values (2, 200);
insert into atest values (3, 300);
insert into atest values (3, 300);

Нужно создать на основе этой таблицы VIEW V_ATEST без дублирующих (идентичных) данных, то есть в которой будет всего три строки:

ID  DATA1
--  -----
1   100
2   200
3   300

Нашел достаточно много советов, как удалять дубликаты данных при помощи DELETE с использованием rowid, но мне он не подходит, так как данные в ATEST должны остаться, и данные нужно занести в новый VIEW.

Подскажите, как это сделать?


Ответы (1 шт):

Автор решения: 0xdb

Представление исключающее дубликаты записей можно создать с DISTINCT | UNIQUE или клаузой GROUP BY.

Tак как на полную длину колонок или некоторые типы данных в листе выборки существуют ограничения, то лучше всегда указывать все колонки явно и отказаться от их неявного (*) привeдения. Оба варианта представления ниже эквивалентны:

create or replace view atestv as
    select distinct id, data1 from atest
/
create or replace view atestv as
    select id, data1 from atest
    group by id, data1 
/
select * from atestv where id=1
/
        ID DATA1 
---------- ------
         1 100   

В задаче с реальными данными ситуация, когда дублирующие записи ничем не отличаются, практически не встречается. Если нет колонки, по которой можно определить порядок дублирующих записей, то очень вероятно, что такая колонка скоро будет добавлена.

В этом случае следует сразу нумеровать записи оконной функцией:

create or replace view atestv as
    with t (id, data1, rn) as (
        select id, data1, row_number () over (partition by id, data1 order by null desc)  
        from atest t)
    select id, data1 from t where rn=1        
/
alter table atest add created timestamp default systimestamp
/
create or replace view atestv as
    with t (id, data1, rn) as (
        select id, data1, row_number () over (partition by id, data1 order by created desc)  
        from atest t)
    select id, data1 from t where rn=1        
/
select * from atestv where id=1
/
        ID DATA1 
---------- ------
         1 100   
→ Ссылка