2009-03-17 18 views
33

Tengo 2 tablas (srcTable1 & destTable) que tienen esquemas idénticos. Estoy tratando de copiar todas las filas de srcTable a destTable e ignorar los duplicados. Pensé que podría simplemente agregar una cláusula WHERE con una subconsulta que me daría solo las filas que no son duplicados. Sin embargo, parece que no funciona. No obtengo ninguna fila insertada o seleccionada.Copie las filas de una tabla a otra, ignorando los duplicados

INSERT INTO destTable 
SELECT * FROM srcTable 
WHERE NOT EXISTS(SELECT * FROM destTable) 

que darse cuenta de que podía hacer algo como esto:

INSERT INTO destTable 
SELECT * FROM srcTable 
WHERE MyKey IN (SELECT MyKey FROM destTable) 

Sin embargo, mis mesas tienen varias claves y no puedo pensar en cómo se puede hacer esto con varias claves.

Alguna idea de lo que estoy haciendo mal o ¿tiene alguna idea mejor?

+0

¿Puede ser un poco más específico en lo que duplica usted está preocupado. ¿Le preocupa la inserción de filas desde el origen que ya están en dest, las filas que están duplicadas en el origen o ambas? – JohnFx

+0

¿Estás usando mysql o mssql? –

Respuesta

43

Su problema es que se necesita otra cláusula where de la sub consulta que identifica lo que hace un duplicado:

INSERT INTO destTable 
SELECT Field1,Field2,Field3,... 
FROM srcTable 
WHERE NOT EXISTS(SELECT * 
       FROM destTable 
       WHERE (srcTable.Field1=destTable.Field1 and 
         SrcTable.Field2=DestTable.Field2...etc.) 
       ) 

Como se ha señalado por otra responde, una combinación externa es probablemente un enfoque más concisa. Mi ejemplo anterior fue solo un intento de explicar el uso de su consulta actual para ser más comprensible. Cualquiera de los enfoques podría funcionar técnicamente.

INSERT INTO destTable 
SELECT s.field1,s.field2,s.field3,... 
FROM srcTable s 
     LEFT JOIN destTable d ON (d.Key1 = s.Key1 AND d.Key2 = s.Key2 AND...) 
WHERE d.Key1 IS NULL 

Ambos enfoques anteriores asumen que está preocupado por la inserción de filas del origen que podrían estar en el destino. Si en cambio está preocupado por la posibilidad de que la fuente tenga filas duplicadas, debería intentar algo como eso.

INSERT INTO destTable 
SELECT Distinct field1,field2,field3,... 
FROM srcTable 

Una cosa más. También sugiero que se enumeren los campos específicos en su declaración de inserción en lugar de usar SELECT *.

+0

Tu primera solución lo hizo. Un JOIN no lo hace porque JOIN solo devuelve filas que las 2 tablas tienen en común. Lo que necesito son las filas que las 2 tablas no tienen en común. –

+0

En realidad, la unión funcionará, pero solo una unión EXTERIOR. Tenga en cuenta la condición de que d.key1 ES NULO, lo que significa que quiere filas sin coincidencia. Por supuesto, tendría que ajustar esa condición para lo que constituye exactamente un duplicado en su escenario. – JohnFx

+0

@JohnFx La combinación funcionó bien para mí, donde tengo una tabla de destinos con una estructura ligeramente diferente. –

4

Algo como esto ?:

INSERT INTO destTable 
SELECT s.* FROM srcTable s 
LEFT JOIN destTable d ON d.Key1 = s.Key1 AND d.Key2 = s.Key2 AND... 
WHERE d.Key1 IS NULL 
+0

Intenté esto, pero no funciona. Una combinación, ya sea INTERIOR o EXTERIOR, solo me dará filas que las 2 tablas tienen en común. Necesito las filas que no tienen en común. Todavía no he encontrado una respuesta a esto. –

+1

Me complace que haya encontrado algo que le sirva, pero su afirmación es * no * correcta. A JOIN (EXTERIOR) JOIN devolverá todas las filas de la tabla de la izquierda, independientemente de si hay una fila correspondiente en la tabla de la derecha. La cláusula WHERE elimina todas las filas resultantes donde hay una coincidencia. –

2

¿Ha intentado SELECT DISTINCT?

INSERT INTO destTable 
SELECT DISTINCT * FROM srcTable 
+0

Intenté esto y no funciona. DISTINCT me dará una lista de filas distintas en la tabla de herramientas. Lo que necesito es una lista distinta cuando las 2 tablas están combinadas. –

0

DISTINCT es la palabra clave que está buscando.

En MSSQL, copiar filas únicas de una tabla a otra se puede hacer así:

SELECT DISTINCT column_name 
INTO newTable 
FROM srcTable 

El column_name es la columna que está buscando los valores únicos de.

Probado y funciona.

+0

Eso podría funcionar si estuviera creando una nueva tabla, pero la tabla fuente ya existe, por lo que no funciona. –

4

espero que esta consulta le ayudará a

INSERT INTO `dTable` (`field1`, `field2`) 
SELECT field1, field2 FROM `sTable` 
WHERE `sTable`.`field1` NOT IN (SELECT `field1` FROM `dTable`) 
+1

Exactamente lo que necesitaba para migrar datos de una versión de marco anterior a una nueva versión de marco donde algunos de los valores ya se habían establecido y faltaban algunos. – JxAxMxIxN

+1

... Aunque eliminé todas las '' marcas por mi sabor de intérprete de SQL. – JxAxMxIxN

15

Comprendo que esto es viejo, pero llegué aquí de Google y después de revisar la respuesta aceptada hice mi propia declaración y funcionó para mí espero que alguien va a encontrar útil:

INSERT IGNORE INTO destTable SELECT id, field2,field3... FROM origTable 

Editar: Esto funciona en MySQL no he probado en MSSQL

+2

Esto solo funciona con MySQL. – ostrokach

+1

Para MySQL necesitaba agregar algo distinto a esto. consulta completa: 'INSERTAR IGNORAR EN la tabla de destino (campo, campo1, campo2) SELECCIONAR campo DISTINCT, campo1, campo2 FROM tabla_de_origen' – Craicerjack

+0

Esto funcionó para mí. Gracias –

1
insert into tbl2 
select field1,field2,... from tbl1 
where not exists 
    ( 
     select field1,field2,... 
     from person2 
     where (tbl1.field1=tbl2.field1 and 
     tbl1.field2=tbl2.field2 and .....) 
    ) 
0

El modo lution que funcionó para mí con PHP/PDO.

public function createTrainingDatabase($p_iRecordnr){ 
// Methode: Create an database envirioment for a student by copying the original 
// @parameter: $p_iRecordNumber, type:integer, scope:local 
// @var: $this->sPdoQuery,   type:string, scope:member 
// @var: $bSuccess,     type:boolean, scope:local 
// @var: $aTables,     type:array,  scope:local 
// @var: $iUsernumber,    type:integer, scope:local 
// @var: $sNewDBName,    type:string, scope:local 
// @var: $iIndex,     type:integer, scope:local 

// -- Create first the name of the new database -- 
$aStudentcard = $this->fetchUsercardByRecordnr($p_iRecordnr); 
$iUserNumber = $aStudentcard[0][3]; 
$sNewDBName = $_SESSION['DB_name']."_".$iUserNumber; 
// -- Then create the new database -- 
$this->sPdoQuery = "CREATE DATABASE `".$sNewDBName."`;"; 
$this->PdoSqlReturnTrue(); 
// -- Create an array with the tables you want to be copied -- 
$aTables = array('1eTablename','2ndTablename','3thTablename'); 
// -- Populate the database -- 
for ($iIndex = 0; $iIndex < count($aTables); $iIndex++) 
{ 
// -- Create the table -- 
    $this->sPdoQuery = "CREATE TABLE `".$sNewDBName."`.`".$aTables[$iIndex]."` LIKE `".$_SESSION['DB_name']."`.`".$aTables[$iIndex]."`;"; 
    $bSuccess = $this->PdoSqlReturnTrue(); 
    if(!$bSuccess){echo("Could not create table: ".$aTables[$iIndex]."<BR>");} 
    else{echo("Created the table ".$aTables[$iIndex]."<BR>");} 
    // -- Fill the table -- 
    $this->sPdoQuery = "REPLACE `".$sNewDBName."`.`".$aTables[$iIndex]."` SELECT * FROM `".$_SESSION['DB_name']."`.`".$aTables[$iIndex]."`"; 
    $bSuccess = $this->PdoSqlReturnTrue(); 
    if(!$bSuccess){echo("Could not fill table: ".$aTables[$iIndex]."<BR>");} 
    else{echo("Filled table ".$aTables[$index]."<BR>");} 
} 

}

Cuestiones relacionadas