Копировать строки из одной таблицы в другую, игнорируя дубликаты - PullRequest
36 голосов
/ 18 марта 2009

У меня есть 2 таблицы (srcTable1 & destTable), которые имеют идентичные схемы. Я пытаюсь скопировать все строки из srcTable в destTable и игнорировать дубликаты. Я подумал, что могу просто добавить предложение WHERE с подзапросом, который даст мне только строки, которые не являются дубликатами Тем не менее, это не похоже на работу. Я не вставляю и не выбираю ни одной строки.

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

Я понимаю, что мог бы сделать что-то вроде этого:

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

Однако в моих таблицах есть несколько ключей, и я не могу представить, как вы могли бы сделать это с несколькими ключами.

Есть идеи, что я делаю неправильно, или у вас есть идеи получше?

Ответы [ 9 ]

46 голосов
/ 18 марта 2009

Ваша проблема в том, что вам нужно другое условие where в подзапросе, которое определяет, что делает дубликат:

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.)
                 )

Как отметил другой ответчик, внешнее соединение, вероятно, является более лаконичным подходом. Приведенный выше пример был просто попыткой объяснить, используя ваш текущий запрос, чтобы быть более понятным. Любой подход может технически сработать.

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

Оба вышеприведенных подхода предполагают, что вас беспокоит вставка строк из источника, которые могут уже находиться в месте назначения. Если вместо этого вас беспокоит вероятность того, что в источнике есть повторяющиеся строки, попробуйте что-то вроде.

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

Еще одна вещь. Я бы также предложил перечислить конкретные поля в вашем операторе вставки вместо использования SELECT *.

17 голосов
/ 12 июня 2013

Я понимаю, что это старый, но я получил здесь от Google и после рассмотрения принятого ответа, я сделал свое собственное заявление, и это сработало для меня, надеюсь, кто-то найдет это полезным:

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

Редактировать: это работает на MySQL, который я не тестировал на MSSQL

4 голосов
/ 03 июня 2013

Надеюсь, этот запрос поможет вам

INSERT INTO `dTable` (`field1`, `field2`)
SELECT field1, field2 FROM `sTable` 
WHERE `sTable`.`field1` NOT IN (SELECT `field1` FROM `dTable`)
4 голосов
/ 18 марта 2009

Как то так?:

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
2 голосов
/ 18 марта 2009

Вы пробовали SELECT DISTINCT?

INSERT INTO destTable
SELECT DISTINCT * FROM srcTable
1 голос
/ 31 марта 2014
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 голосов
/ 25 июля 2018

Вы пытались сначала удалить дубликаты в подзапросе?

INSERT INTO destTable
SELECT source.* FROM(
    SELECT *
    FROM srcTable
    EXCEPT
    SELECT src.* FROM
    srcTable AS src
    INNER JOIN destTable AS dest 
    /* put in below line the conditions to match repeated registers */
        ON dest.SOME_FANCY_MATCH = src.SOME_FANCY_MATCH AND ... 
) as source

Если наборы очень большие, возможно, это не лучшее решение.

0 голосов
/ 06 марта 2016

Решение, которое работало для меня с 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>");}
}

}

0 голосов
/ 18 марта 2009

DISTINCT - ключевое слово, которое вы ищете.

В MSSQL копирование уникальных строк из таблицы в другую можно сделать так:

SELECT DISTINCT column_name
INTO newTable
FROM srcTable

column_name - это столбец, в котором вы ищете уникальные значения.

Проверено и работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...