Borrando filas duplicadas en Teradata.

Teradata no tiene el concepto de ROWID que maneja Oracle. Así, el código de identificación de la fila en el bloque (Row Hash + Order) no es accesible como en Oracle para acceder directamente a ella. Esto provoca un problema: en Teradata NO podemos eliminar filas duplicadas de una tabla ‘MULTISET’ mediante su ‘ROWID’. (Esta es precisamente una de las razones por las que Teradata prefiere tablas ‘SET’).

Normalmente lo que se hace es un INSERT…SELECT DISTINCT a una tabla temporal para luego renombrarla o borrar la tabla original completamente y hacer otro INSERT…SELECT desde la tabla temporal a la original. Esto hace que tengamos que crear tabla nueva y mover muchos datos.

Pero si tenemos una tabla grande con pocos duplicados y no queremos hacer una tabla temporal nueva y andar moviendo todos los datos de acá para allá y vuelta, podríamos hacer algo así:

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
CREATE MULTISET TABLE MY_DB.PRUEBA01,
 NO JOURNAL,
 NO FALLBACK
 (ID_N SMALLINT NOT NULL,
  C_TXT VARCHAR(10) NULL)
 PRIMARY INDEX(ID_N)
 ;

 *** Table has been created.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA01 VALUES (1,'UNO');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA01 VALUES (1,'UNO');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA01 VALUES (1,'UNO');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA01 VALUES (1,'UNO');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA01 VALUES (2,'DOS');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA01 VALUES (2,'DOS');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

INSERT INTO MY_DB.PRUEBA01 VALUES (3,'TRES');

 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT *
  FROM MY_DB.PRUEBA01
  ORDER BY ID_N;

 *** Query completed. 7 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

  ID_N  C_TXT
------  ----------
     1  UNO
     1  UNO
     1  UNO
     1  UNO
     2  DOS
     2  DOS
     3  TRES

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
ALTER TABLE MY_DB.PRUEBA01 ADD MY_ROWNUM SMALLINT;

 *** Table has been modified.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
INSERT INTO MY_DB.PRUEBA01 ( ID_N,
       C_TXT,
       MY_ROWNUM )
SELECT ID_N,
       C_TXT,
       2
  FROM MY_DB.PRUEBA01
  QUALIFY ROW_NUMBER() OVER (PARTITION BY ID_N ORDER BY ID_N) = 2
;

 *** Insert completed. 2 rows added.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
DELETE FROM MY_DB.PRUEBA01 a
WHERE a.MY_ROWNUM IS NULL
  AND EXISTS ( SELECT NULL
                 FROM MY_DB.PRUEBA01 b
                WHERE a.ID_N = b.ID_N
                AND b.MY_ROWNUM = 2)
;

 *** Delete completed. 6 rows removed.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
ALTER TABLE  MY_DB.PRUEBA01 DROP MY_ROWNUM;

 *** Table has been modified.
 *** Total elapsed time was 1 second.

 BTEQ -- Enter your DBC/SQL request or BTEQ command:
SELECT *
  FROM MY_DB.PRUEBA01
  ORDER BY ID_N;

 *** Query completed. 3 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

  ID_N  C_TXT
------  ----------
     1  UNO
     2  DOS
     3  TRES

 BTEQ -- Enter your DBC/SQL request or BTEQ command:

No es muy elegante, y además estamos haciendo dos DDL (ALTER TABLE), pero en determinadas circunstancias puede ser una solución válida.

(También podríamos hacer una tabla temporal sólo para los ‘MY_ROWNUM = 2′ y modificar el DELETE para usar esta temporal en el ‘EXISTS’ y luego hacer un INSERT…SELECT desde ella).

Saludos.

Carlos.

About these ads

3 respuestas a Borrando filas duplicadas en Teradata.

  1. marcelo miorelli dice:

    carlos,
    jo creo que tengo una version un poquito mejor.
    aqui estas:

    – delete the duplicate records from table @t
    – keeping a single unit of each
    – marcelo miorelli 31-oct-2012

    declare @t table ([key] int )

    insert into @t select 1
    insert into @t select 1
    insert into @t select 1
    insert into @t select 2
    insert into @t select 2
    insert into @t select 3
    insert into @t select 4
    insert into @t select 4
    insert into @t select 4
    insert into @t select 4
    insert into @t select 4
    insert into @t select 5
    insert into @t select 5
    insert into @t select 5
    insert into @t select 5
    insert into @t select 5
    insert into @t select 6
    insert into @t select 6
    insert into @t select 6
    insert into @t select 7
    insert into @t select 7
    insert into @t select 8
    insert into @t select 8
    insert into @t select 9
    insert into @t select 9
    insert into @t select 9
    insert into @t select 9
    insert into @t select 9

    select * from @t

    ; with cte as (
    select *
    , row_number() over (partition by [Key] order by [Key]) as Picker
    from @t
    )
    delete cte
    where Picker > 1

    select * from @t

    • CarlosAL dice:

      Marcelo

      No sé sobre qué RDBMS estarás ejecutando tu ‘versión un poquito mejor’, pero definitivamente NO es Teradata.

      “The only SQL DML statement that can be modified with a WITH or WITH RECURSIVE modifier is SELECT”

      Saludos.

      Carlos.

  2. Dany dice:

    select co1, col2, count(*) from table1 group by col1, col2 having count(*)>1

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 45 seguidores

%d personas les gusta esto: