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.
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
Marcelo
No sé sobre qué RDBMS estarás ejecutando tu ‘versión un poquito mejor’, pero definitivamente NO es Teradata.
Saludos.
Carlos.