内部连接到临时表并在MySql中插入表中

问题描述 投票:0回答:2

我有一个字符串列表。每个类别都有一个以'/'分隔的类别。

例如:

动物/家养/狗

动物/家养/猫

我要对这些类别进行的操作是将其插入MySql类别表。该表有4列:id(int自动递增),category_name(nvarchar),parent_id(int),is_active(位)

围绕这些插入的逻辑应如下:

[主要类别(动物)的parent_id应该为0。

子类别将其父代的ID作为parent_id。

不能有两个活动类别具有相同的类别名称。

我已经尝试实现以下逻辑:

  1. 获取不同的字符串列表。

  2. 从这些中,获得主要类别的不同列表。

  3. 将父ID为0的不同主要类别插入类别表。

  4. 成对组织每个类别并获得不同的对:

((动物,家畜)

(家养,狗)

[(家养,猫)

  1. 获取每个父类别的匹配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;           

问题:运行查询后,我希望类别表中有4个条目。

Expected

但是我只得到2。

Actual

我可以看到临时表在进行最后一个内部联接之前具有正确的条目。我似乎无法弄清楚为什么类别表没有其他两行。

高度赞赏任何朝着正确方向的指导。

更新#1假设规范说“不能有两个活动类别具有相同的类别名称具有相同的父ID”。例如,如果有两个字符串作为(animals / domestic / cat),(animals / outdoor / cat),则应为cat设置两个条目,其ID为国内和室外ID为parent_id。

mysql sql insert inner-join temp-tables
2个回答
1
投票
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


0
投票

在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 <>小提琴。

不幸的是,这在早期版本中要痛苦得多。

© www.soinside.com 2019 - 2024. All rights reserved.