我有一个字符串列表。每个类别都有一个以'/'分隔的类别。
例如:
动物/家养/狗
动物/家养/猫
我要对这些类别进行的操作是将其插入MySql类别表。该表有4列:id(int自动递增),category_name(nvarchar),parent_id(int),is_active(位)
围绕这些插入的逻辑应如下:
[主要类别(动物)的parent_id应该为0。
子类别将其父代的ID作为parent_id。
不能有两个活动类别具有相同的类别名称。
我已经尝试实现以下逻辑:
获取不同的字符串列表。
从这些中,获得主要类别的不同列表。
将父ID为0的不同主要类别插入类别表。
成对组织每个类别并获得不同的对:
((动物,家畜)
(家养,狗)
[(家养,猫)
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;
问题:运行查询后,我希望类别表中有4个条目。
但是我只得到2。
我可以看到临时表在进行最后一个内部联接之前具有正确的条目。我似乎无法弄清楚为什么类别表没有其他两行。
高度赞赏任何朝着正确方向的指导。
更新#1假设规范说“不能有两个活动类别具有相同的类别名称具有相同的父ID”。例如,如果有两个字符串作为(animals / domestic / cat),(animals / outdoor / cat),则应为cat设置两个条目,其ID为国内和室外ID为parent_id。
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 |活跃-:| :------------ | --------:| :--------1 |动物| 0 | 1个4 |国内| 1 | 1个7 |狗| 4 | 1个8 |猫| 4 | 1个
db <>小提琴here
在MySQL 8中,您可以通过一个查询来完成此操作:
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 <>小提琴。
不幸的是,这在早期版本中要痛苦得多。