我正在尝试创建一个子表,该子表从现有表的字段中的一组字符串中派生而来。现有字段由我需要解析的一组字符串组成。参见下面的数据示例:
+------------------------------------------------------------+
| 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中还有另一则与此主题相关的帖子,请提供并将其标记为重复。
答案 0 :(得分:1)
假设现在是您的桌子:
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;
用parent_table
中的ID填充tmp_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
主要思想是将tmp_table
的序列号从0到999(由递归CTE生成)连接起来,并使用这些数字从JSON数组中提取相应的元素。
答案 1 :(得分: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;