restricciones - SQL: solo selecciona la fila que no está duplicada
sql eliminar registros repetidos dejando solo 1 (5)
Necesito transferir datos de una tabla a otra. La segunda tabla tiene una restricción de clave primaria (y la primera no tiene restricción). Ellos tienen la misma estructura. Lo que quiero es seleccionar todas las filas de la tabla A e insertarlas en la tabla B sin la fila duplicada (si una fila es duplicada, solo quiero tomar la primera que encontré)
Ejemplo:
MyField1 (PK) | MyField2 (PK) | MyField3(PK) | MyField4 | MyField5
----------
1 | ''Test'' | ''A1'' | ''Data1'' | ''Data1''
2 | ''Test1'' | ''A2'' | ''Data2'' | ''Data2''
2 | ''Test1'' | ''A2'' | ''Data3'' | ''Data3''
4 | ''Test2'' | ''A3'' | ''Data4'' | ''Data4''
Como puede ver, la segunda y la tercera línea obtuvieron la misma clave pk, pero diferentes datos en MyField4 y MyField5. Entonces, en este ejemplo, me gustaría tener la primera, segunda y cuarta fila. No es el tercero porque es una duplicación del segundo (incluso si MyField4 y MyField5 contienen datos diferentes).
¿Cómo puedo hacer eso con una sola selección?
Gracias
¿Cuál es tu base de datos? En Oracle podrías decir
SELECT FROM your_table
WHERE rowid in
(SELECT MIN(rowid)
FROM your_table
GROUP BY MyField1, MyField2, MyField3);
Tenga en cuenta que es algo incierto cuál de las filas con la misma PK se considerará "primero". Si necesita imponer un pedido específico, debe ordenar adicionalmente las otras columnas.
No estoy seguro de cómo sabe cuál de la fila 2 y la fila 3 desea en la nueva tabla, pero en mysql puede simplemente:
insert ignore into new_table (select * from old_table);
Y el PK no permitirá que se inserten entradas duplicadas.
Primero, debe definir qué hace que una fila sea "primera". Crearé una definición arbitraria y puede cambiar el SQL según lo necesite para lo que desee. Para este ejemplo, supongo que "primero" es el valor más bajo para MyField4 y si son iguales, entonces el valor más bajo para MyField5. También representa la posibilidad de que las 5 columnas sean idénticas.
SELECT DISTINCT
T1.MyField1,
T1.MyField2,
T1.MyField3,
T1.MyField4,
T1.MyField5
FROM
MyTable T1
LEFT OUTER JOIN MyTable T2 ON
T2.MyField1 = T1.MyField1 AND
T2.MyField2 = T1.MyField2 AND
T2.MyField3 = T1.MyField3 AND
(
T2.MyField4 > T1.MyField4 OR
(
T2.MyField4 = T1.MyField4 AND
T2.MyField5 > T1.MyField5
)
)
WHERE
T2.MyField1 IS NULL
Si también desea contabilizar los PK que no están duplicados en la tabla de origen, pero que ya existen en su tabla de destino, deberá dar cuenta de eso también.
CREATE TABLE #A(
ID INTEGER IDENTITY,
[MyField1] [int] NULL,
[MyField2] [varchar](10) NULL,
[MyField3] [varchar](10) NULL,
[MyField4] [varchar](10) NULL,
[MyField5] [varchar](10) NULL
)
INSERT INTO #A (MyField1,MyField2,MyField3,MyField4,MyField5) SELECT * FROM A
insert into B
select MyField1,MyField2,MyField3,MyField4,MyField5 from #A a1
where not exists (select id from #A a2 where a2.MyField1 = a1.MyField1 and a2.ID < a1.ID)
DROP TABLE #A
O
insert into b
select distinct * from a a1
where not exists (
select a2.MyField1 from a a2 where a1.MyField1 = a2.MyField1 and
(a1.MyField2 < a2.MyField2 or a1.MyField3 < a2.MyField3
or a1.MyField4 < a2.MyField5 or a1.MyField5 < a2.MyField5))
Depende de lo que estés buscando.
Hay una gran diferencia entre utilizar JOIN
+ WHERE NULL
, NOT IN
y NOT EXISTS
, incluido el rendimiento, que es más importante con conjuntos de datos más grandes.
(Ver NO EN CONTRA NO EXISTE vs. MEZCLAR IZQUIERDA / ES NULO )
Los tres métodos que se muestran en el artículo vinculado son bastante sencillos.