SQL - только выбрать строку, которая не дублируется - PullRequest
3 голосов
/ 10 февраля 2009

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

Пример:

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 содержат разные данные).

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

1010 * ТНХ *

Ответы [ 5 ]

4 голосов
/ 10 февраля 2009

Во-первых, вам нужно определить, что делает строку «первой». Я составлю произвольное определение, и вы сможете изменить SQL так, как вам нужно. В этом примере я предполагаю, что «first» будет самым низким значением для 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

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

3 голосов
/ 10 февраля 2009

Не знаю, откуда вы знаете, какую строку 2 и строку 3 вы хотите добавить в новую таблицу, но в mysql вы можете просто:

insert ignore into new_table (select * from old_table);

И PK не позволит вставлять дублирующиеся записи.

2 голосов
/ 10 февраля 2009

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

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

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

1 голос
/ 12 января 2012

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

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

(См. НЕ ВНУТРИ против НЕ СУЩЕСТВУЕТ против ЛЕВОГО СОЕДИНЕНИЯ / НУЛЬ .)

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

0 голосов
/ 10 февраля 2009
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

OR

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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...