SQL Merge / Group строк в одну - PullRequest
       7

SQL Merge / Group строк в одну

0 голосов
/ 10 октября 2018

Я хотел бы знать, что является наиболее оптимизированным SQL для этой проблемы.Я должен применить запрос SQL к таблице, которая содержит недопустимые данные, чтобы исправить все эти недопустимые данные.Таблица структурирована следующим образом:

TABLE(customer_id, start_date, end_date, type)

В настоящее время таблица может содержать много строк для данного кортежа (customer_id, type).Мой запрос должен «объединить» все строки, принадлежащие группе, в одну и сохранить самую последнюю дату для начальной даты и самую старую для конечной даты:

Cust1;01/01/2012;01/01/2020;1
Cust1;01/01/2010;01/01/2024;1

должен преобразоваться в одну строку

Cust1;01/01/2012;01/01/2024;1

I необходимо исправить данные, а не только выделить их : удалить строки, если их больше 1, и извлечь данные из каждой!Я надеюсь, что мои объяснения достаточно ясны!Я работаю с СУБД Oracle

Спасибо,

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

У агрегации:

select customer_id, max(start_date), max(end_date), type
from table t
group by customer_id, type;
0 голосов
/ 10 октября 2018

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

Поэтому сначала проверьте количество дублированных строк

with clean as (
select CUSTOMER_ID, TYPE, max(start_date) start_date_clean, max(end_date)  end_date_clean
from tab group by CUSTOMER_ID, TYPE)
select tab.*, start_date_clean, end_date_clean
from tab join clean on tab.CUSTOMER_ID = clean.CUSTOMER_ID and tab.TYPE = clean.TYPE
where  start_date != start_date_clean or  end_date != end_date_clean
;

Этот запросвернет все строки, которые будут обработаны, т. е. либо начальная, либо конечная дата не верны.

Если это число большое - следуйте указаниям другого ответа - скопируйте таблицу и замените исходную таблицу наcopy.

Если ** число маленькое *, выберите update / delete:

update tab a
set a.START_DATE = (select max(b.START_DATE) from tab b where a.customer_id = b.customer_id and a.type = b.type),
a.END_DATE = (select max(b.END_DATE) from tab b where a.customer_id = b.customer_id and a.type = b.type)
where (a.customer_id, a.type) in 
( 
select tab.CUSTOMER_ID, tab.TYPE 
from tab join 
(select CUSTOMER_ID, TYPE, max(start_date) start_date_clean, max(end_date)  end_date_clean
from tab group by CUSTOMER_ID, TYPE) clean 
on tab.CUSTOMER_ID = clean.CUSTOMER_ID and tab.TYPE = clean.TYPE
where  start_date != start_date_clean or  end_date != end_date_clean);

Обновление во всех затронутых строках start и end дата для правильных значений.

пример

CUSTOMER_ID START_DATE          END_DATE                  TYPE
----------- ------------------- ------------------- ----------
          1 01-01-2013 00:00:00 01-01-2016 00:00:00          1 
          1 01-01-2012 00:00:00 01-01-2018 00:00:00          1 
          1 01-01-2010 00:00:00 01-01-2017 00:00:00          1 
          2 01-01-2010 00:00:00 01-01-2018 00:00:00          1 
          3 01-01-2010 00:00:00 01-01-2018 00:00:00          1

обновлен до

CUSTOMER_ID START_DATE          END_DATE                  TYPE
----------- ------------------- ------------------- ----------
          1 01-01-2013 00:00:00 01-01-2018 00:00:00          1 
          1 01-01-2013 00:00:00 01-01-2018 00:00:00          1 
          1 01-01-2013 00:00:00 01-01-2018 00:00:00          1 
          2 01-01-2010 00:00:00 01-01-2018 00:00:00          1 
          3 01-01-2010 00:00:00 01-01-2018 00:00:00          1 

На следующем шаге дублированные строки должны быть удалены.Это делает следующее удаление: какой пользователь ROW_NUMBER идентифицирует дубликаты:

delete from tab where rowid in 
(select RID from (
  select rowid rid,
  row_number() over (partition by CUSTOMER_ID, TYPE order by null) rn
  from tab) 
where rn > 1)
;

Что вы видите - метод копирования brute force прост в запросах, но оставляет таблицу в автономном режимена некоторое время.Для его выполнения требуется вдвое больше места, и это займет некоторое время.

Подход update является более сложным, но обходится без окна обслуживания и выполняется быстро.

0 голосов
/ 10 октября 2018

использование max() функция

    select customer_id,type, max(start_date),max(end_date)
    from t1
    group by customer_id,type

я думаю, что вы хотите создать другую таблицу, используя эти данные

 create table test_t as
 select customer_id,type, max(start_date),max(end_date)
        from t1
        group by customer_id,type 
...