#mysql
#mysql
Вопрос:
У меня есть целевая таблица t1, подобная этой (parent и parent_country — соответствующий идентификатор) с несколькими тысячами записей:
id parent parent_country name type
1 0 0 USA country
2 0 0 Canada country
3 1 1 Alabama state
4 1 1 California state
5 4 1 Los Angeles city
...
и исходная таблица t2, подобная этой, с несколькими тысячами записей:
loc_text_1 loc_text_2 loc_text_3
Long Beach California USA
Frankfurt Hessen Germany
Los Angeles California USA
...
Как я могу вставить значения из t2 В t1 и, кроме того (конечно), только те города, штаты и страны, которых еще нет в t1? (идентификатор в t1 является автоматически сохраняемым первичным ключом)
Комментарии:
1. Известно ли, что имена состояний уникальны? Это несколько упростило бы запросы, необходимые для этого.
2. Таблица
t1
пуста?3. @PaulSpiegel У меня есть целевая таблица t1 … с несколькими тысячами записей:
4. Есть ли какие-либо УНИКАЛЬНЫЕ ключи в
t1
? Вам лучше просто опубликовать инструкции crate для обеих таблиц. ИспользуйтеSHOW CREATE TABLE <table name>
5. @Martin Нет, ни один столбец (кроме id) не уникален. Могут быть дубликаты, такие как, например: Лонг-Бич в Калифорнии и Лонг-Бич в Нью-Йорке.
Ответ №1:
Добавьте УНИКАЛЬНЫЙ КЛЮЧ на (parent, name)
для t1
.
alter table t1 add unique (parent, name);
Этот способ вы можете использовать INSERT IGNORE
, чтобы избежать вставки дубликатов.
Затем скопируйте сначала страны, затем штаты, а затем города:
-- copy countries
insert ignore into t1(parent, parent_country, name, type)
select distinct 0, 0, loc_text_3, 'country'
from t2
;
-- copy states
insert ignore into t1(parent, parent_country, name, type)
select distinct t1.id, t1.id, t2.loc_text_2, 'state'
from t2
join t1 on t1.name = t2.loc_text_3
where t1.type = 'country'
;
-- copy cities
insert ignore into t1(parent, parent_country, name, type)
select st.id, st.parent, t2.loc_text_1, 'city'
from t2
join t1 st on st.name = t2.loc_text_2
join t1 co on co.name = t2.loc_text_3 and co.id = st.parent
where st.type = 'state'
and co.type = 'country'
;
Демонстрация: https://www.db-fiddle.com/f/hhpkvgFK6opjFmZwYb7QFv/0
Комментарии:
1. У меня получилось отлично. Большое спасибо!
Ответ №2:
Я думаю, вы можете достичь желаемых результатов, выполнив 3 отдельных INSERT
этапа: один для стран, затем один для штатов и, наконец, один для городов:
INSERT INTO t1 (parent, parent_country, name, type)
SELECT DISTINCT 0, 0, loc_text_3, 'country'
FROM t2
WHERE NOT EXISTS (SELECT name
FROM t1
WHERE name = t2.loc_text_3 AND type = 'country')
INSERT INTO t1 (parent, parent_country, name, type)
SELECT DISTINCT t1.id, t1.id, t2.loc_text_2, 'state'
FROM t2
JOIN t1 ON t1.name = t2.loc_text_3 AND t1.type = 'country'
WHERE NOT EXISTS (SELECT name
FROM t1 t1s
WHERE parent = t1.id
AND name = t2.loc_text_2
AND type = 'state')
INSERT INTO t1 (parent, parent_country, name, type)
SELECT DISTINCT t1.id, t1c.id, t2.loc_text_1, 'city'
FROM t2
JOIN t1 ON t1.name = t2.loc_text_2 AND t1.type = 'state'
JOIN t1 t1c ON t1c.name = t2.loc_text_3 AND t1c.type = 'country' AND t1c.id = t1.parent
WHERE NOT EXISTS (SELECT name
FROM t1 t1t
WHERE parent = t1.id
AND parent_country = t1c.id
AND name = t2.loc_text_1
AND type = 'city')
Вывод (для ваших выборочных данных):
id parent parent_country name type
1 0 0 USA country
2 0 0 Canada country
3 1 1 Alabama state
4 1 1 California state
5 4 1 Los Angeles city
6 0 0 Germany country
7 6 6 Hessen state
8 4 1 Long Beach city
9 7 6 Frankfurt city
Комментарии:
1. Вам нужно
DISTICT
везде. dbfiddle.uk /…2. @PaulSpiegel спасибо за это. Я обновил ответ.
3. Учтите, что в разных странах могут быть города с одинаковым названием. Вам нужно больше условий в подзапросах NOT EXISTS.
4. @PaulSpiegel это было намного сложнее, чем я изначально предполагал. Думаю, теперь у меня это есть.
5. Это происходит и со мной тоже. Просыпаюсь утром с новой идеей, трачу часы вчерашней работы, переписываю ее за 10 минут 🙂