Как вставить с помощью обратного JOIN на нескольких клавишах? - PullRequest
2 голосов
/ 18 июня 2009

Как сделать обратное соединение с более чем одним ключевым столбцом?

В этом примере SqlServer для детской игрушки у меня есть

CREATE TABLE [dbo].[CarList](
 [myID] [int] IDENTITY(1,1) NOT NULL,
 [CarColour] [varchar](32) NOT NULL,
 [CarName] [varchar](128) NOT NULL,
 [CarCompany] [varchar](32) NOT NULL,

 CONSTRAINT [PK_CarList] PRIMARY KEY CLUSTERED(
  [myID] ASC,
  [CarColour] ASC,
  [CarName] ASC,
  [CarCompany] ASC
 )
)

GO

INSERT INTO CarList (CarColour, CarName, CarCompany)
VALUES('blue', 'Abe', 'Ford')

В другом месте в БД у меня есть таблица, как

CREATE TABLE [dbo].[NewCars](
 [CarColour] [varchar](32) NOT NULL,
 [CarName] [varchar](128) NOT NULL,
 [CarCompany] [varchar](32) NOT NULL,
)

GO

INSERT INTO NewCars (CarColour, CarName, CarCompany)
SELECT 'blue', 'Abe', 'Ford'
 UNION ALL
SELECT 'blue', 'Abe', 'GM'
 UNION ALL
SELECT 'blue', 'Betty', 'Ford'
 UNION ALL
SELECT 'green', 'Abe', 'Honda'

Теперь я хочу добавить автомобили, которых у меня нет в таблице CarList

Что-то вроде ...

INSERT INTO CarList ( CarColour, CarName, CarCompany)
 SELECT DISTINCT new.CarColour, new.CarName, new.CarCompany
 FROM    NewCars new, CarList old
 WHERE   new.CarColour  <> old.CarColour
     AND new.CarName    <> old.CarName
     AND new.CarCompany <> old.CarCompany

Что не работает, потому что строки "blue", "Betty", "Ford" будут отфильтрованы ...

Если бы это был какой-то один идентификатор, это было бы очень просто

INSERT INTO myTable (myID, param1, param2, etc)
SELECT param1, param2, etc
FROM someOtherTable new
WHERE new.myID NOT IN (SELECT myID FROM myTable)

По причинам, в которые я действительно не хочу входить, я не могу удалить строки из NewCars, которые соответствуют CarList. Я также должен сделать это за один проход, если это возможно.

[править] Спасибо, ребята!

Ответы [ 4 ]

5 голосов
/ 18 июня 2009
INSERT
INTO    CarList ( CarColour, CarName, CarCompany)
SELECT  CarColour, CarName, CarCompany
FROM    NewCars nc
WHERE   NOT EXISTS
        (
        SELECT  1
        FROM    CarList cl
        WHERE   cl.CarColor = nc.CarColor
                AND cl.CarName  = nc.CarName
                AND cl.CarCompany = nc.CarCompany
        )
5 голосов
/ 18 июня 2009

спасибо за DDL и DML

Вот один из способов

INSERT INTO CarList ( CarColour, CarName, CarCompany)
 SELECT DISTINCT *
 FROM    NewCars n
where not exists (select 1 from CarList c where c.CarColour =n.CarColour
and c.CarName = n.CarName
and c.CarCompany = n.CarCompany)

Существует как минимум 4 способа сделать это

  • NOT IN (не будет работать для более чем одного столбца, как у вас)
  • НЕ СУЩЕСТВУЕТ
  • Влево и вправо присоединиться
  • НАРУЖНОЕ ПРИМЕНЕНИЕ (2005+)
  • ИСКЛЮЧИТЬ (2005 +)

Чтение Выбор всех строк из одной таблицы, которые не существуют в другой таблице

1 голос
/ 18 июня 2009

Я бы, наверное, использовал:

INSERT INTO CarList(CarColour, CarName, CarCompany)
SELECT
     NC.CarColour,
     NC.CarName,
     NC.CarCompany
FROM
     NewCars NC
LEFT OUTER JOIN CarList CL ON
     CL.CarColour = NC.CarColour AND
     CL.CarName = NC.CarName AND
     CL.CarCompany = NC.CarCompany
WHERE
     CL.MyID IS NULL
1 голос
/ 18 июня 2009
INSERT INTO CarList ( CarColour, CarName, CarCompany) 
SELECT DISTINCT new.CarColor, new.CarName, new.CarCompany 
FROM    NewCar new
where not exists (select 0 
         from  CarList old 
         WHERE   new.CarColour  = old.CarColour     
         AND new.CarName    = old.CarName     
         AND new.CarCompany = old.CarCompany)
--This statement matches all that does exists in carlist
--and insert everything that does not exists in Carlist
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...