【问题标题】:Create a child table from an existing field MySQL从现有字段 MySQL 创建子表
【发布时间】:2019-03-05 16:16:59
【问题描述】:

我正在尝试创建一个子表,该子表派生自现有表中的字段的一组字符串。现有字段由一组我需要解析的字符串组成。请参阅下面的数据示例:

+------------------------------------------------------------+
|                           Column                           |
+------------------------------------------------------------+
| ['ffffffff-11111-1111-baaa-xxxx']'                         |
| ['zxyvvv-1234567-abcdefghijk', '1234567-abcdefg-hijklmn']' |
+------------------------------------------------------------+

目标是从现有字段中获取字符串集并创建一个新表,这些字符串可以使用某种类型的外键连接回父表。

Parent table
+--------+
| Col_id |
+--------+
|      1 |
|      2 |
+--------+

Child Table

+-----------+-------------------------------+
| Col_id    |            Column             |
+-----------+-------------------------------+
|         1 | ffffffff-11111-1111-baaa-xxxx |
|         2 | zxyvvv-1234567-abcdefghijk    |
|         2 | 1234567-abcdefg-hijklmn       |
+-----------+-------------------------------+

在处理这种情况时,我不确定正确的方法或“最佳做法”。我还假设我需要在引用父表的子表中创建一个外键来执行连接。如果 Stack Overflow 中还有其他与此主题相关的帖子,请提供并将其标记为重复。

【问题讨论】:

  • 这不是一个经典的sql任务,你能不能用一些脚本语言,甚至sql存储过程都可以解决问题
  • 您在Column 中拥有的最大值数是多少?
  • @GordonLinoff 列字段中可能最多有 4 个值

标签: mysql sql foreign-keys relational-database


【解决方案1】:

您可以通过以下方式提取列:

select substring_index(column, ',', 1) as data
from t
union all
select substring_index(substring_index(column, ',', 2), -1) as data
from t
where column like '%,%'
union all
select substring_index(substring_index(column, ',', 3), -1) as data
from t
where column like '%,%,%'
union all
select substring_index(substring_index(column, ',', 4), -1) as data
from t
where column like '%,%,%,%';

获取孩子 ID 比较麻烦。您可以使用原始列和一些变量来执行此操作:

select c.col_id, t.data
from (select column, substring_index(column, ',', 1) as data
      from t
      union all
      select column, substring_index(substring_index(column, ',', 2), -1) as data
      from t
      where column like '%,%'
      union all
      select column, substring_index(substring_index(column, ',', 3), -1) as data
      from t
      where column like '%,%,%'
      union all
      select column, substring_index(substring_index(column, ',', 4), -1) as data
      from t
      where column like '%,%,%,%'
     ) t join
     (select column, (@rn := @rn + 1) as col_id
      from t cross join
           (select @rn := 0) params
     ) c
     on t.column = c.column;

【讨论】:

    【解决方案2】:

    带有 JSON 和 CTE 的 MySQL 8 解决方案

    假设现在这是你的桌子:

    create table old_table(
      data text
    );
    insert into old_table(data)values
      ("['ffffffff-11111-1111-baaa-xxxx']"),
      ("['zxyvvv-1234567-abcdefghijk', '1234567-abcdefg-hijklmn']");
    

    并且您想将数据“传输”到两个新表中:

    create table parent_table(
      parent_id int primary key
    );
    
    create table child_table(
      child_id int auto_increment primary key,
      parent_id int not null,
      data varchar(100),
      foreign key (parent_id) references parent_table(parent_id)
    );
    

    首先使用 AUTO_INCREMENT id 列创建旧表的(临时)副本:

    create table tmp_table(
      id int auto_increment primary key,
      data json
    );
    

    从旧表复制时将数据转换为 JSON:

    insert into tmp_table(data)
      select replace(data, "'", '"') from old_table;
    

    tmp_table中的ID填充parent_table

    insert into parent_table(parent_id)
      select id from tmp_table;
    

    现在(主要部分)用以下查询填充child_table

    insert into child_table(parent_id, data)
      with recursive seq(i) as ( -- sequence numbers 0 to 999
        select 0
        union all
        select i + 1
        from seq
        where i < 999
      )
      select t.id as parent_id
           , json_unquote(json_extract(t.data, concat('$[', s.i, ']'))) as data
      from tmp_table t
      join seq s on s.i <= json_length(t.data)-1;
    

    child_table 现在包含以下数据:

    child_id    parent_id   data
    1           1           ffffffff-11111-1111-baaa-xxxx
    2           2           zxyvvv-1234567-abcdefghijk
    3           2           1234567-abcdefg-hijklmn
    

    db-fiddle demo

    主要思想是将序列号从 0 到 999(使用递归 CTE 生成)的tmp_table 连接起来,并使用这些数字从 JSON 数组中提取相应的元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 2021-06-23
      • 2018-11-12
      相关资源
      最近更新 更多