如果您知道您的 user_action 列中没有太多操作,您可以对 union all 使用递归子查询,从而避免使用 aux numbers 表。
但它要求您知道每个用户的操作数,要么调整初始表,要么为其创建视图或临时表。
数据准备
假设您有这样的表格:
create temporary table actions
(
user_id varchar,
user_name varchar,
user_action varchar
);
我将在其中插入一些值:
insert into actions
values (1, 'Shone', 'start,stop,cancel'),
(2, 'Gregory', 'find,diagnose,taunt'),
(3, 'Robot', 'kill,destroy');
这是一个带有临时计数的附加表
create temporary table actions_with_counts
(
id varchar,
name varchar,
num_actions integer,
actions varchar
);
insert into actions_with_counts (
select user_id,
user_name,
regexp_count(user_action, ',') + 1 as num_actions,
user_action
from actions
);
这将是我们的“输入表”,它看起来和您预期的一样
select * from actions_with_counts;
| id |
name |
num_actions |
actions |
| 2 |
Gregory |
3 |
find,diagnose,taunt |
| 3 |
Robot |
2 |
kill,destroy |
| 1 |
Shone |
3 |
start,stop,cancel |
同样,您可以调整初始表,从而跳过将计数添加为单独的表。
子查询以展平动作
这是取消嵌套的查询:
with recursive tmp (user_id, user_name, idx, user_action) as
(
select id,
name,
1 as idx,
split_part(actions, ',', 1) as user_action
from actions_with_counts
union all
select user_id,
user_name,
idx + 1 as idx,
split_part(actions, ',', idx + 1)
from actions_with_counts
join tmp on actions_with_counts.id = tmp.user_id
where idx < num_actions
)
select user_id, user_name, user_action as parsed_action
from tmp
order by user_id;
这将为每个操作创建一个新行,输出如下所示:
| user_id |
user_name |
parsed_action |
| 1 |
Shone |
start |
| 1 |
Shone |
stop |
| 1 |
Shone |
cancel |
| 2 |
Gregory |
find |
| 2 |
Gregory |
diagnose |
| 2 |
Gregory |
taunt |
| 3 |
Robot |
kill |
| 3 |
Robot |
destroy |