按条件连接字符串

Posted

技术标签:

【中文标题】按条件连接字符串【英文标题】:Concatenate string by a condition 【发布时间】:2021-04-07 14:06:19 【问题描述】:

我想根据与user_id 关联的其他行的条件为新列分配值。

例如当 device 从桌面更改为移动时,然后将 desktop > mobile 分配给该 user_id 的所有记录。 当有两个以上不同的变化时,例如从平板电脑到桌面和桌面到移动设备,那么 tablet > desktop > mobile

这里是示例数据:

+---------+-------+---------+
| user_id | step  | device  |
+---------+-------+---------+
| 7bc6de  | step1 | desktop |
| 7bc6de  | step2 | desktop |
| 7bc6de  | step3 | mobile  |
| 7bc6de  | step4 | mobile  |
| 7bc6de  | step5 | desktop |
| 0ee6df  | step1 | tablet  |
| 0ee6df  | step2 | tablet  |
| 0ee6df  | step3 | desktop |
| 0ee6df  | step4 | desktop |
| 0ee6df  | step5 | mobile  |
+---------+-------+---------+

期望的输出:

+---------+-------+---------+---------------------------+
| user_id | step  | device  |    device_concatenated    |
+---------+-------+---------+---------------------------+
| 7bc6de  | step1 | desktop | desktop > mobile          |
| 7bc6de  | step2 | desktop | desktop > mobile          |
| 7bc6de  | step3 | mobile  | desktop > mobile          |
| 7bc6de  | step4 | mobile  | desktop > mobile          |
| 7bc6de  | step5 | desktop | desktop > mobile          |
| 0ee6df  | step1 | tablet  | tablet > desktop > mobile |
| 0ee6df  | step2 | tablet  | tablet > desktop > mobile |
| 0ee6df  | step3 | desktop | tablet > desktop > mobile |
| 0ee6df  | step4 | desktop | tablet > desktop > mobile |
| 0ee6df  | step5 | mobile  | tablet > desktop > mobile |
+---------+-------+---------+---------------------------+

其他场景:

在表格中,有重复的步骤,即用户可以在不同的时间使用不同的设备看到相同的步骤。在这种情况下,如何在预期结果中进行如下更改,让每个用户和设备迈出第一步?

+---------+-------+---------------------+---------+
| user_id | step  |     created_at      | device  |
+---------+-------+---------------------+---------+
| user1   | step1 | 2021-03-16 14:03:16 | mobile  |
| user1   | step2 | 2021-03-16 14:04:07 | mobile  |
| user1   | step2 | 2021-03-16 14:03:47 | desktop |
| user1   | step3 | 2021-03-16 14:03:55 | mobile  |
| user1   | step3 | 2021-03-16 14:04:00 | mobile  |
| user1   | step1 | 2021-03-16 14:04:02 | desktop |
| user1   | step2 | 2021-03-16 14:03:16 | mobile  |
| user1   | step3 | 2021-03-16 14:04:07 | mobile  |
| user1   | step4 | 2021-03-16 14:04:08 | desktop |
| user1   | step4 | 2021-03-16 14:04:09 | tablet  |
+---------+-------+---------------------+---------+

预期结果:

+---------+-------+---------------------+---------+---------------------+
| user_id | step  |     created_at      | device  | device_concatenated |
+---------+-------+---------------------+---------+---------------------+
| user1   | step1 | 2021-03-16 14:03:16 | mobile  | mobile > desktop    |
| user1   | step2 | 2021-03-16 14:03:16 | mobile  | mobile > desktop    |
| user1   | step3 | 2021-03-16 14:03:55 | mobile  | mobile > desktop    |
| user1   | step4 | 2021-03-16 14:04:08 | desktop | mobile > desktop    |
+---------+-------+---------------------+---------+---------------------+

【问题讨论】:

【参考方案1】:

https://www.db-fiddle.com/f/ooSmXAxqVHNxqD8sJ6wZfr/0

with first_seen_per_user_and_device AS (
select user_id, device, min(step) first_seen_step
from input_data
group by user_id, device
),
user_to_devices as(
SELECT user_id, array_to_string(
  array_agg(device order by first_seen_step), ' > ') device_concatenated
  from first_seen_per_user_and_device
group by 1
)
SELECT input_data.*, device_concatenated 
from input_data
join user_to_devices
  ON user_to_devices.user_id = input_data.user_id;

如果可以在多个设备上看到同一个用户和步骤,您需要添加一个额外的 WITH 子句以仅选择您想要的一个(例如,最早的一个),使用 SELECT DISTINCT

https://www.db-fiddle.com/f/w9ZRvpQ7KXgdVKCTDAb43o/0

WITH input_data as (
  select distinct on (user_id, step) user_id, step, created_at, device
  from input_data_with_created_at
  ORDER BY user_id, step, created_at
), 
(...) -- Rest of the CTEs, same as before but with timestamp included.

【讨论】:

你可以使用string_agg 我试过了,但是couldn't get it to work。不知道为什么... @AdamKG 我意识到我的表格中有重复的步骤,即用户可以在不同的时间使用不同的设备看到相同的步骤。将此作为附加问题添加,您介意看一下吗?

以上是关于按条件连接字符串的主要内容,如果未能解决你的问题,请参考以下文章

Javascript竞争条件多个承诺连接字符串

Pyspark:使用转换类型作为字符串的多重连接条件

bash shell 脚本:条件字符串连接

使用三元条件运算符对系列进行 Python 字符串连接

如果在 R 中满足条件,则从前一行获取值并连接

为啥 C 在使用条件运算符时不允许连接字符串?