SQL Вставить несколько строк для каждого идентификатора, возвращенного из другой таблицы, если строка для этого идентификатора не существует - PullRequest
0 голосов
/ 11 марта 2020

Мне нужно вставить несколько строк в таблицу для каждого возвращенного идентификатора из другой таблицы.

Например, table1

id | thing1 |
---+--------|
1  |  true
2  |  false
3  |  true
4  |  false
5  |  true

Пример table2

id |  table1_id  |     column3    |    column4   |
---+-------------|----------------|--------------|
1  |     1       |     'fizz'     |    'fizz'
2  |     1       |     'buzz'     |    'buzz'
3  |     1       | 'hello world'  | 'hello world'
4  |     2       |     'fizz'     |    'fizz'
5  |     2       |     'buzz'     |    'buzz'
6  |     2       | 'hello world'  | 'hello world'

I нужно получить каждый идентификатор из таблицы выше, где thing1 имеет значение true, и вставить несколько строк в таблицу2 с соответствующим идентификатором, а также с 2 другими строками.

SELECT id FROM table1 WHERE thing1 = true

вернет идентификатор 1, 3 и 5.

Я хотел бы вставить несколько строк, добавляя идентификатор из таблицы 1, а также 2 другие строки в таблицу 2.

INSERT into table2 (table1_id, column3, column4)
VALUES 
    (*id*, 'fizz', 'fizz')
    (*id*, 'buzz', 'buzz')
    (*id*, 'hello world', 'hello world')

Я знаю, как получить идентификаторы и как вручную вставить, но как я могу сделать оба с одним утверждением?

1 Ответ

0 голосов
/ 11 марта 2020

Я бы предложил INSERT ... SELECT следующим образом:

INSERT into table2 (table1_id, column3, column4)
SELECT t1.id, s.str, s.str
FROM table1 AS t1
CROSS JOIN (SELECT "fizz" AS str UNION SELECT "buzz" UNION SELECT "hello world") AS s
LEFT JOIN table2 AS t2 ON t1.id = t2.table1_id AND s.str = t2.column3
WHERE t1.thing1 = true
    AND t2.id IS NULL -- Only insert when they are not already present
;

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

У меня есть У меня не было особого требования использовать CROSS JOINs, поэтому я не уверен, насколько хорошо они играют с левыми соединениями, поэтому, если вышеприведенное не сработает, вот несколько альтернатив ниже:

INSERT into table2 (table1_id, column3, column4)
SELECT t1.id, s.str, s.str
FROM table1 AS t1
CROSS JOIN (SELECT "fizz" AS str UNION SELECT "buzz" UNION SELECT "hello world") AS s
WHERE t1.thing1 = true
    AND (t2.id, s.str) NOT IN (SELECT table1_id, column3 FROM table2 )
;

или

INSERT into table2 (table1_id, column3, column4)
SELECT t1.id, s.str, s.str
FROM table1 AS t1
CROSS JOIN (SELECT "fizz" AS str UNION SELECT "buzz" UNION SELECT "hello world") AS s
WHERE t1.thing1 = true
    AND NOT EXISTS (
           SELECT * 
           FROM table2 AS t2 
           WHERE t2.table1_id = t1.id AND t2.column3 = s.str
        )
;

Если Sql Сервер, подзапрос объединения (включая окружающие скобки и псевдоним) можно заменить на (VALUES ('fizz'), ('buzz'), ('hello word')) AS s(str).

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