内部连接到 temp table 并插入到 table in MySql
Inner joining on to temp table and insert to table in MySql
我有一个字符串列表。他们每个人都有类别,由'/'分隔。
例如:
animals/domestic/dog
animals/domestic/cat
我想对这些类别执行的操作是插入 MySql 个类别 table。
table 有 4 列:
id(整数自动递增),category_name(nvarchar),parent_id(整数),is_active(位)
插入这些的逻辑如下:
主要类别(动物)的 parent_id 应为 0。
子类别的父类别 ID 为 parent_id。
不能有两个具有相同类别名称的活动类别。
我尝试实现了以下逻辑:
获取不同的字符串列表。
从中得到一个不同的主要类别列表。
将不同的主要类别插入父 ID 为 0 的类别 table。
将每个类别成对组织并获得不同的对:
(动物,家养)
(家养,狗)
(国产,猫)
- 获取每个父类别的匹配 ID 并插入子类别的 parent_id
SQL:
/*INSERT ALL THE FIRST PARENT CATEGORIES WITH A PARENT ID OF 0*/
INSERT INTO categories (category_name, parent_id, is_active)
VALUES ('animals', 0, 1);
/*INSERT ALL THE CATEGORIES IN PAIRS TO TEMP TABLE*/
CREATE TEMPORARY TABLE tempcat(parent nvarchar(256), child nvarchar(256));
INSERT INTO tempcat
VALUES ('animals', 'domestic'),('domestic', 'dog'),('domestic','cat');
/*INSERT INTO THE CATEGORIES TABLE*/
INSERT INTO categories(category_name, parent_id, is_active)
SELECT tempcat.child, categories.id, 1
FROM categories
INNER JOIN tempcat
ON categories.category_name = tempcat.parent;
WHERE categories.is_active = 1;
/*DISPOSE THE TEMPORARY TABLE*/
DROP TEMPORARY TABLE tempcat;
问题:
在查询为 运行 之后,我希望在类别 table 中有 4 个条目。
但是我只得到2个
我可以看到临时 table 在执行最后一个内部联接之前有正确的条目。
我似乎无法弄清楚为什么类别 table 没有其他两行。
非常感谢任何正确方向的指导。
更新 #1
假设规格说 'There cannot be two active categories with the same category name that had the same parent IDs'。
例如,如果有两个字符串 (animals/domestic/cat)、(animals/outdoor/cat),则应该有两个 ID 为国内和室外的猫条目,如 parent_id's.
在 MySQL8 中,您可以使用单个查询来完成此操作:
with splits as (
select 1 as n, substring_index(cats, '/', 1) as cat, cats
from strings union all
select 2 as n, substring_index(substring_index(cats, '/', 2), '/', -1) as cat, cats
from strings
where cats like '%/%' union all
select 3 as n, substring_index(substring_index(cats, '/', 3), '/', -1) as cat, cats
from strings
where cats like '%/%/%'
),
splits_n as (
select s.*, dense_rank() over (order by n, cat) as new_id
from splits s
),
splits_np as (
select s.*, sp.new_id as parent_id
from splits_n s left join
splits_n sp
on sp.cats = s.cats and sp.n = s.n - 1
)
select distinct new_id as id, cat, parent_id, 1 as is_active
from splits_np s;
Here 是一个 db<>fiddle.
不幸的是,这在早期版本中要痛苦得多。
CREATE TABLE categories (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
category_name VARCHAR(64),
parent_id INT UNSIGNED NOT NULL DEFAULT 0,
is_active CHAR(1) NULL,
UNIQUE INDEX idx_name_active (category_name));
CREATE TABLE source_data (path TEXT);
INSERT INTO source_data VALUES ('animals/domestic/dog'), ('animals/domestic/cat');
CREATE PROCEDURE update_categories_table()
BEGIN
DECLARE cnt INT DEFAULT 0;
INSERT IGNORE INTO categories (category_name, parent_id, is_active)
SELECT SUBSTRING_INDEX(path, '/', 1), 0, '1'
FROM source_data;
iteration: LOOP
SELECT COUNT(*) INTO cnt
FROM source_data
WHERE LOCATE('/', path);
IF NOT cnt THEN
LEAVE iteration;
END IF;
INSERT IGNORE INTO categories (category_name, parent_id, is_active)
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(source_data.path, '/', 2), '/', -1),
categories.id,
'1'
FROM source_data, categories
WHERE SUBSTRING_INDEX(source_data.path, '/', 1) = categories.category_name;
UPDATE source_data
SET path = SUBSTRING(path FROM 1 + LOCATE('/', path));
END LOOP iteration;
TRUNCATE source_data;
END
call update_categories_table;
SELECT * FROM categories;
id | category_name | parent_id | is_active
-: | :------------ | --------: | :--------
1 | animals | 0 | 1
4 | domestic | 1 | 1
7 | dog | 4 | 1
8 | cat | 4 | 1
db<>fiddle here
我有一个字符串列表。他们每个人都有类别,由'/'分隔。
例如:
animals/domestic/dog
animals/domestic/cat
我想对这些类别执行的操作是插入 MySql 个类别 table。 table 有 4 列: id(整数自动递增),category_name(nvarchar),parent_id(整数),is_active(位)
插入这些的逻辑如下:
主要类别(动物)的 parent_id 应为 0。
子类别的父类别 ID 为 parent_id。
不能有两个具有相同类别名称的活动类别。
我尝试实现了以下逻辑:
获取不同的字符串列表。
从中得到一个不同的主要类别列表。
将不同的主要类别插入父 ID 为 0 的类别 table。
将每个类别成对组织并获得不同的对:
(动物,家养)
(家养,狗)
(国产,猫)
- 获取每个父类别的匹配 ID 并插入子类别的 parent_id
SQL:
/*INSERT ALL THE FIRST PARENT CATEGORIES WITH A PARENT ID OF 0*/
INSERT INTO categories (category_name, parent_id, is_active)
VALUES ('animals', 0, 1);
/*INSERT ALL THE CATEGORIES IN PAIRS TO TEMP TABLE*/
CREATE TEMPORARY TABLE tempcat(parent nvarchar(256), child nvarchar(256));
INSERT INTO tempcat
VALUES ('animals', 'domestic'),('domestic', 'dog'),('domestic','cat');
/*INSERT INTO THE CATEGORIES TABLE*/
INSERT INTO categories(category_name, parent_id, is_active)
SELECT tempcat.child, categories.id, 1
FROM categories
INNER JOIN tempcat
ON categories.category_name = tempcat.parent;
WHERE categories.is_active = 1;
/*DISPOSE THE TEMPORARY TABLE*/
DROP TEMPORARY TABLE tempcat;
问题: 在查询为 运行 之后,我希望在类别 table 中有 4 个条目。
但是我只得到2个
我可以看到临时 table 在执行最后一个内部联接之前有正确的条目。 我似乎无法弄清楚为什么类别 table 没有其他两行。
非常感谢任何正确方向的指导。
更新 #1 假设规格说 'There cannot be two active categories with the same category name that had the same parent IDs'。 例如,如果有两个字符串 (animals/domestic/cat)、(animals/outdoor/cat),则应该有两个 ID 为国内和室外的猫条目,如 parent_id's.
在 MySQL8 中,您可以使用单个查询来完成此操作:
with splits as (
select 1 as n, substring_index(cats, '/', 1) as cat, cats
from strings union all
select 2 as n, substring_index(substring_index(cats, '/', 2), '/', -1) as cat, cats
from strings
where cats like '%/%' union all
select 3 as n, substring_index(substring_index(cats, '/', 3), '/', -1) as cat, cats
from strings
where cats like '%/%/%'
),
splits_n as (
select s.*, dense_rank() over (order by n, cat) as new_id
from splits s
),
splits_np as (
select s.*, sp.new_id as parent_id
from splits_n s left join
splits_n sp
on sp.cats = s.cats and sp.n = s.n - 1
)
select distinct new_id as id, cat, parent_id, 1 as is_active
from splits_np s;
Here 是一个 db<>fiddle.
不幸的是,这在早期版本中要痛苦得多。
CREATE TABLE categories (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, category_name VARCHAR(64), parent_id INT UNSIGNED NOT NULL DEFAULT 0, is_active CHAR(1) NULL, UNIQUE INDEX idx_name_active (category_name));
CREATE TABLE source_data (path TEXT); INSERT INTO source_data VALUES ('animals/domestic/dog'), ('animals/domestic/cat');
CREATE PROCEDURE update_categories_table() BEGIN DECLARE cnt INT DEFAULT 0; INSERT IGNORE INTO categories (category_name, parent_id, is_active) SELECT SUBSTRING_INDEX(path, '/', 1), 0, '1' FROM source_data; iteration: LOOP SELECT COUNT(*) INTO cnt FROM source_data WHERE LOCATE('/', path); IF NOT cnt THEN LEAVE iteration; END IF; INSERT IGNORE INTO categories (category_name, parent_id, is_active) SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(source_data.path, '/', 2), '/', -1), categories.id, '1' FROM source_data, categories WHERE SUBSTRING_INDEX(source_data.path, '/', 1) = categories.category_name; UPDATE source_data SET path = SUBSTRING(path FROM 1 + LOCATE('/', path)); END LOOP iteration; TRUNCATE source_data; END
call update_categories_table; SELECT * FROM categories;
id | category_name | parent_id | is_active -: | :------------ | --------: | :-------- 1 | animals | 0 | 1 4 | domestic | 1 | 1 7 | dog | 4 | 1 8 | cat | 4 | 1
db<>fiddle here