Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Problema envolvendo a cabeça em torno da consulta de exclusão SQL complexa


Comece identificando os cadastros dos demais clientes de um cadastro. Aqui está uma visão:
create view groups as 
select   a.Client_id
       , c.Registration_id
from AssociatedClient as a 
join AssociatedClient as b on a.Registration_id = b.Registration_id 
join AssociatedClient as c on b.Client_id = c.Client_id;

Isso nos dá:
select Client_id
    , min(Registration_id) as first
    , max(Registration_id) as last
    , count(distinct Registration_id) as regs
    , count(*) as pals
from  groups 
group by Client_id;
Client_id   first       last        regs        pals      
----------  ----------  ----------  ----------  ----------
2           2           8           4           5         
3           2           8           4           18        
4           5           5           1           1         
5           2           8           4           5         
7           10          10          1           1         
8           9           9           1           1         

Você não precisa de uma visão, é claro; é apenas por conveniência. Você poderia simplesmente usar uma mesa virtual. Mas inspecione-o com cuidado para se convencer de que produz a faixa certa de "registros de amigos" para cada cliente. Observe que a visualização não referência Registration . Isso é significativo porque produz os mesmos resultados mesmo depois de usá-lo para excluir de Registration , para que possamos usá-lo para a segunda instrução delete.

Agora temos uma lista de clientes e seus "registros de amigos". Qual é a data do último registro de cada amigo?
select g.Client_id, max(Registration_date) as last_reg
from groups as g join Registration as r
on g.Registration_id = r.Id
group by g.Client_id;
g.Client_id  last_reg  
-----------  ----------
2            2011-10-14
3            2011-10-14
4            2011-10-07
5            2011-10-14
7            2011-10-17
8            2011-10-14

Quais têm uma data mais recente antes de uma hora certa?
select g.Client_id, max(Registration_date) as last_reg
from groups as g join Registration as r
on g.Registration_id = r.Id
group by g.Client_id
having max(Registration_date) < '2011-10-08';
g.Client_id  last_reg  
-----------  ----------
4            2011-10-07

IIUC isso significaria que o cliente #4 deve ser excluído, e qualquer coisa para o qual ele se registrou deve ser excluído. As inscrições seriam
select * from Registration
where Id in (
      select Registration_id from groups as g
      where Client_id in ( 
            select g.Client_id
            from groups as g join Registration as r
            on g.Registration_id = r.Id
            group by g.Client_id
            having max(Registration_date) < '2011-10-08'
      )
);
Id          Registration_date
----------  -----------------
5           2011-10-07       

E, com certeza, o cliente nº 4 está no Registro nº 5 e é o único cliente sujeito a exclusão por este teste.

A partir daí você pode fazer o delete declarações. Acho que a regra é "excluir o cliente e tudo o que ele registrou". Nesse caso, eu provavelmente escreveria os IDs de registro em uma tabela temporária e escreveria as exclusões para Registration e AssociatedClient juntando-se a ele.