2009-02-10 2 views
3

Мне нужно перенести данные из одной таблицы в другую. Вторая таблица получила ограничение первичного ключа (и первое не имеет ограничений). Они имеют одинаковую структуру. То, что я хочу, чтобы выбрать все строки из таблицы A и вставить его в таблице B без дублирования строки (если строка is0 дубликат, я только хочу, чтобы взять первый я нашел)SQL - выберите только строку, которая не дублируется

Пример:

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' 

Как вы можете видеть, вторая и третья строки получили один и тот же ключ pk, но разные данные в MyField4 и MyField5. Итак, в этом примере я хотел бы иметь первую, вторую и четвертую строки. Не третий, потому что это дублирование второго (даже если MyField4 и MyField5 содержат разные данные).

Как я могу сделать это с помощью одного выбора?

thx

+0

MySql, Oracle, MS Sql или что-то еще? – BenMaddox

ответ

4

Во-первых, вам нужно определить, что делает строку «первой». Я сделаю произвольное определение, и вы можете изменить SQL так, как вам нужно, для чего вы хотите. В этом примере я предполагаю, что «первым» является самым низким значением для MyField4, и если они равны, то самое низкое значение для MyField5. Это также объясняет возможность идентичности всех 5 столбцов.

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 

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

2

Какова Ваша база данных? В Oracle вы можете сказать

SELECT FROM your_table 
WHERE rowid in 
(SELECT MIN(rowid) 
FROM your_table 
GROUP BY MyField1, MyField2, MyField3); 

Обратите внимание, что несколько неопределенно, какая из строк с тем же PK будет считаться «первой». Если вам нужно наложить определенный порядок, вам необходимо дополнительно сортировать остальные столбцы.

+0

Запустил бы этот вложенный оператор select один раз для каждой строки в вашей_ таблице? Если да, то вы получите довольно плохую производительность. Надеемся, что вложенный оператор будет кэширован. Не тот, кто знаком с частью планирования запроса. – Bassam

+0

Я использую MS SQL 2005, но я думаю, что этот синтаксис будет работать, я постараюсь завтра, и я дам вам знать. Спасибо! – Melursus

+0

Он не будет запускаться для каждой строки только один раз. – Thilo

3

Не знаю, как вы знаете, какой из строки 2 и 3 грести вы хотите в новой таблице, но в MySQL вы можете просто:

insert ignore into new_table (select * from old_table); 

И PK не позволит дублированные записи для вставки.

+0

, который спас мой день! – trante

0
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 

ИЛИ

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

Это зависит от того, что вы ищете.

Там большая разница между использованием JOIN + WHERE NULL, NOT IN и NOT EXISTS, в том числе производительности, что более важно, с большими наборами данных.

(см NOT IN vs. NOT EXISTS vs. LEFT JOIN/IS NULL.)

три метода, показанные в связанной статье довольно проста.

Смежные вопросы