Eliminar duplicidade

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
tayna2oo9
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Qua, 16 Abr 2014 2:17 pm

Amigos, bom dia!

Peço gentilmente orientação para resolver esta situação que dias vem me tirando o sono.
Tenho a seguinte SQL

Selecionar tudo

select

 T.NR_SEQ_ORDEM_SERV N_ORDEM,
 S.DT_ORDEM_SERVICO ABERTO,
 obter_dif_data( S.DT_ORDEM_SERVICO,T.DT_HISTORICO,0) HORA_FECHADA_REAL  ,  
 S.IE_PRIORIDADE
 
    from MAN_ORDEM_SERVICO S,
         MAN_ORDEM_SERV_TECNICO T
    
where
(T.NR_SEQ_ORDEM_SERV = S.NR_SEQUENCIA)
AND (S.dt_ordem_servico between :dt_inicial and :dt_final)
AND (S.IE_PRIORIDADE =:prioridade or S.IE_PRIORIDADE =:prioridade2) -- Prioridede de U e E
AND (S.NR_GRUPO_PLANEJ=81)

order by 1,2 asc
Que retorna

N_ORDEM ABERTO HORA_FECHADA_REAL IE_PRIORIDADE

Selecionar tudo

69121	02/01/2014 10:22:51	22:37:08	E
69121	02/01/2014 10:22:51	00:36:26	E
69139	02/01/2014 14:06:35	154:53:28	E
69139	02/01/2014 14:06:35	19:55:56	E
69168	03/01/2014 08:56:07	136:03:56	E
69168	03/01/2014 08:56:07	00:44:13	E
69173	03/01/2014 09:43:57	135:16:06	E
69173	03/01/2014 09:43:57	00:36:09	E
69176	03/01/2014 10:40:48	170:46:29	U
69176	03/01/2014 10:40:48	170:46:39	U
69176	03/01/2014 10:40:48	76:05:08	U
69182	03/01/2014 12:54:54	69:28:16	E
69182	03/01/2014 12:54:54	204:05:15	E
69182	03/01/2014 12:54:54	69:36:13	E
69184	03/01/2014 13:20:12	188:53:30	U
69184	03/01/2014 13:20:12	68:57:26	U
69184	03/01/2014 13:20:12	188:53:39	U
69202	03/01/2014 16:22:48	00:07:20	E
69202	03/01/2014 16:22:48	416:37:19	E
69224	06/01/2014 08:04:46	136:55:23	E
69224	06/01/2014 08:04:46	04:41:14	E
69233	06/01/2014 09:28:27	135:31:42	E
69233	06/01/2014 09:28:27	00:37:39	E
69325	08/01/2014 08:35:25	23:54:27	U
69325	08/01/2014 08:35:25	33:03:03	U
69325	08/01/2014 08:35:25	33:03:08	U
69326	08/01/2014 08:36:30	52:47:21	U
69326	08/01/2014 08:36:30	52:47:12	U
69326	08/01/2014 08:36:30	00:40:00	U
69431	10/01/2014 09:42:16	264:06:41	E
69431	10/01/2014 09:42:16	288:28:42	E
69431	10/01/2014 09:42:16	266:54:28	E
69431	10/01/2014 09:42:16	241:05:32	E
69431	10/01/2014 09:42:16	174:49:10	E
69431	10/01/2014 09:42:16	122:44:50	E
69431	10/01/2014 09:42:16	127:00:48	E
69431	10/01/2014 09:42:16	124:42:30	E
69431	10/01/2014 09:42:16	172:54:40	E
69431	10/01/2014 09:42:16	172:54:32	E
69431	10/01/2014 09:42:16	143:50:40	E
69431	10/01/2014 09:42:16	121:27:28	E
69455	10/01/2014 15:33:43	297:26:26	E
69455	10/01/2014 15:33:43	160:50:47	E
69553	14/01/2014 11:37:34	373:22:33	U
69553	14/01/2014 11:37:34	03:54:51	U
Peço gentilmente orientações para remover N_ORDEM duplicatas porém com horas maior, exemplo:

Selecionar tudo

69121	02/01/2014 10:22:51	22:37:08	E
69121	02/01/2014 10:22:51	00:36:26	E 
a SQL deveria exibir somente

Selecionar tudo

69121	02/01/2014 10:22:51	00:36:26	E
, pois contem menos horas.

Desde de já agradeço a atenção de todos, muito obrigado.
Avatar do usuário
adrianoturbo
Moderador
Moderador
Mensagens: 393
Registrado em: Qui, 20 Mar 2008 4:09 pm
Localização: Brasília
Adriano Alves
---Para cada problema dificil existe uma solução simples.----

Sister Tayna ,utilize o distinct ou unique pra evitar a duplicidade :

Selecionar tudo

    select  distinct

    T.NR_SEQ_ORDEM_SERV N_ORDEM,
    S.DT_ORDEM_SERVICO ABERTO,
    obter_dif_data( S.DT_ORDEM_SERVICO,T.DT_HISTORICO,0) HORA_FECHADA_REAL  , 
    S.IE_PRIORIDADE

        from MAN_ORDEM_SERVICO S,
             MAN_ORDEM_SERV_TECNICO T
       
    where
    (T.NR_SEQ_ORDEM_SERV = S.NR_SEQUENCIA)
    AND (S.dt_ordem_servico between :dt_inicial and :dt_final)
    AND (S.IE_PRIORIDADE =:prioridade or S.IE_PRIORIDADE =:prioridade2) -- Prioridede de U e E
    AND (S.NR_GRUPO_PLANEJ=81)

    order by 1,2 asc

tayna2oo9
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Qua, 16 Abr 2014 2:17 pm

Adriano, bom dia!

Obrigado pela atenção, porém sua sugestão não surtiu o efeito esperado, repara que a hora é diferente, e quero exibir somente as horas menor, descartar a maior.
Avatar do usuário
adrianoturbo
Moderador
Moderador
Mensagens: 393
Registrado em: Qui, 20 Mar 2008 4:09 pm
Localização: Brasília
Adriano Alves
---Para cada problema dificil existe uma solução simples.----

Tayna,faz um agrupamento usando group by
tayna2oo9
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Qua, 16 Abr 2014 2:17 pm

Boa tarde, Realizei group by.. não obtive exito.
tayna2oo9
Rank: Estagiário Pleno
Rank: Estagiário Pleno
Mensagens: 4
Registrado em: Qua, 16 Abr 2014 2:17 pm

Boa tarde, na tentativa de resolver minha situação tentei fazer um subselect, roda normalmente porém não está respeitando a condição, ou seja ainda contina a trazer informações indevidas. alguém pode me orientar, obrigado

Selecionar tudo

SELECT 
        A.NR_SEQUENCIA,
        B.DT_ATUALIZACAO,
        obter_dif_data( A.DT_ORDEM_SERVICO,B.DT_HISTORICO,0) HORA_FECHADA_REAL,
        A.IE_PRIORIDADE,
        A.NR_GRUPO_PLANEJ
        
       FROM MAN_ORDEM_SERVICO A,
            MAN_ORDEM_SERV_TECNICO B
       
       WHERE
A.NR_SEQUENCIA = B.NR_SEQ_ORDEM_SERV
AND(A.NR_GRUPO_PLANEJ =81)
AND(A.IE_PRIORIDADE <> 'B')  
AND(A.IE_STATUS_ORDEM = 2)
AND( A.DT_ORDEM_SERVICO BETWEEN :dt_inicial and :dt_final)
[b]AND (B.DT_ATUALIZACAO < (SELECT C.DT_ATUALIZACAO FROM  MAN_ORDEM_SERV_TECNICO C WHERE ROWNUM = 1 AND (C.NR_SEQ_ORDEM_SERV = B.NR_SEQ_ORDEM_SERV)))[/b]

ORDER BY 1,3 ASC
tora34
Rank: Analista Pleno
Rank: Analista Pleno
Mensagens: 108
Registrado em: Qua, 12 Nov 2008 6:01 pm
Localização: Campo Mourão PR
Renato Pasquini
Oracle Developer

Bom dia Tanya,
estou tentando entender sua dúvida e a query enviada, o que a função obter_dif_data faz?
Poderia tentar explicar a real necessidade desta query? Que tipo de resultado você pretende apresentar para o usuário final?
gesiel
Rank: Estagiário Júnior
Rank: Estagiário Júnior
Mensagens: 1
Registrado em: Qua, 16 Jul 2014 1:12 pm

Tayna,

acredito que já tenha resolvido, mas vai uma sugestão:

Selecionar tudo

SELECT 
 ORDEM,
 ABERTO,
 MIN(HORA_FECHADA_REAL) HORA_FECHADA,
 PRIORIDADE
 FROM
 (
 select  distinct

    T.NR_SEQ_ORDEM_SERV N_ORDEM,
    S.DT_ORDEM_SERVICO ABERTO,
    obter_dif_data( S.DT_ORDEM_SERVICO,T.DT_HISTORICO,0) HORA_FECHADA_REAL  , 
    S.IE_PRIORIDADE PRIORIDADE

        from MAN_ORDEM_SERVICO S,
             MAN_ORDEM_SERV_TECNICO T
       
    where
    (T.NR_SEQ_ORDEM_SERV = S.NR_SEQUENCIA)
    AND (S.dt_ordem_servico between :dt_inicial and :dt_final)
    AND (S.IE_PRIORIDADE =:prioridade or S.IE_PRIORIDADE =:prioridade2) -- Prioridede de U e E
    AND (S.NR_GRUPO_PLANEJ=81)
) X
GROUP BY ORDEM, ABERTO, PRIORIDADE
    order by 1,2 asc;

boa sorte
Avatar do usuário
stcoutinho
Moderador
Moderador
Mensagens: 850
Registrado em: Qua, 11 Mai 2011 5:15 pm
Localização: são Paulo - SP

Olá tayna2oo9,

Uma outra forma de resolver esta questão poderia ser o uso da função de DENSE_RANK. Esta função permite que você classifique os resultados da querie conforme um critério, atribuindo uma nota (ou rank) para o resultado retornado.

Para um melhor entendimento, execute os passos abaixo:

A) Tente atribuir uma classificação para os resultados da queire. Para isso, use o DENSE_RANK, agrupando os resultados por t.nr_seq_ordem_serv,s.dt_ordem_servico,s.ie_prioridade e depois ordenando os mesmos por obter_dif_data(s.dt_ordem_servico, t.dt_historico, 0). A queire abaixo (que eventualmente precise ser revisada) lhe permite visualizar os dados:

Selecionar tudo

SELECT t.nr_seq_ordem_serv n_ordem,
               s.dt_ordem_servico aberto,
               obter_dif_data(s.dt_ordem_servico, t.dt_historico, 0) hora_fechada_real,
               s.ie_prioridade,
               DENSE_RANK() OVER (PARTITION BY t.nr_seq_ordem_serv,s.dt_ordem_servico,s.ie_prioridade ORDER BY obter_dif_data(s.dt_ordem_servico, t.dt_historico, 0) ASC) AS RANK
          FROM man_ordem_servico s, 
               man_ordem_serv_tecnico t
         WHERE (t.nr_seq_ordem_serv = s.nr_sequencia)
           AND (s.dt_ordem_servico BETWEEN :dt_inicial and :dt_final)
           AND (s.ie_prioridade = :prioridade OR s.ie_prioridade = :prioridade2) 
           AND (s.nr_grupo_planej = 81)
Você vai notar que a ultima coluna RANK apresenta valores como 1,2,3. Quando a querie apresentar um valor maior do que 1, então se tratam de registros duplicados.

B) O proximo passo é filtrar nas queries os registros que lhe interessam. Neste caso, devemos selecionar os registros com rank=1, que significa que para um determinado t.nr_seq_ordem_serv,s.dt_ordem_servico,s.ie_prioridade, este seria a diferença de menor valor.
Execute então a querie abaixo:

Selecionar tudo

SELECT n_ordem,
       aberto,
       hora_fechada_real,
       ie_prioridade
  FROM (SELECT t.nr_seq_ordem_serv n_ordem,
               s.dt_ordem_servico aberto,
               obter_dif_data(s.dt_ordem_servico, t.dt_historico, 0) hora_fechada_real,
               s.ie_prioridade,
               DENSE_RANK() OVER (PARTITION BY t.nr_seq_ordem_serv,s.dt_ordem_servico,s.ie_prioridade ORDER BY obter_dif_data(s.dt_ordem_servico, t.dt_historico, 0) ASC) AS RANK
          FROM man_ordem_servico s, 
               man_ordem_serv_tecnico t
         WHERE (t.nr_seq_ordem_serv = s.nr_sequencia)
           AND (s.dt_ordem_servico BETWEEN :dt_inicial and :dt_final)
           AND (s.ie_prioridade = :prioridade OR s.ie_prioridade = :prioridade2) 
           AND (s.nr_grupo_planej = 81)
 WHERE rank = 1           
 ORDER BY 1, 2 ASC
Para um melhor entendimento/aprendizado, neste link do ORACLE-BASE você encontra um excelente artigo que explica esta função em maiores detalhes: http://www.oracle-base.com/articles/mis ... ctions.php

Boa sorte,

Sergio Coutinho
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 17 visitantes