拆分 space 分隔值并将它们映射到 SQLite 中的原始 ID?

Split space separated values and map them to original ID in SQLite?

我有一个名为 personal_websessions 的 table,它包含以下格式的数据:

 id_no | website_link 
 1     | google.com msn.com gmail.com 
 2     | whosebug.com reddit.com 
 3     | msn.com 

您可以使用以下 SQL 命令创建此 table:

CREATE TABLE personal_websessions(id_no INTEGER PRIMARY KEY, website_link TEXT);
INSERT INTO personal_websessions VALUES(1, 'google.com msn.com gmail.com'), (2, 'whosebug.com reddit.com'), (3, 'msn.com ');

我想将 website_link 列的值拆分为 spaces ' ' 以获得以下 table 结果:

id_no | website_link 
1     | google.com
1     | msn.com 
1     | gmail.com
2     | whosebug.com
2     | reddit.com
3     | msn.com

我想将 website_link 列拆分为 单个 space 以实现此目的 - 我尝试了不同的方法,包括此处概述的方法:

我知道有一种方法可以使用 sqlite 来执行此操作,但我还没有弄明白!任何帮助是极大的赞赏!

谢谢 - Goosfraba

用递归CTE:

with recursive cte as (
  select id_no, trim(website_link) || ' ' website_link,
    substr(
      website_link, 
      1, 
      case 
        when website_link like '% %' then instr(website_link, ' ') - 1
        else website_link
      end
    ) link
  from personal_websessions
  union all                                                     
  select c.id_no, substr(c.website_link, length(c.link) + 2),
    substr(
      substr(c.website_link, length(c.link) + 2), 
      1, 
      instr(substr(c.website_link, length(c.link) + 2), ' ') - 1
    ) link
  from cte c                                               
  where substr(c.website_link, length(c.link) + 2) like '% %'
)
select id_no, link website_link
from cte
order by id_no

参见demo
结果:

| id_no | website_link      |
| ----- | ----------------- |
| 1     | google.com        |
| 1     | msn.com           |
| 1     | gmail.com         |
| 2     | whosebug.com |
| 2     | reddit.com        |
| 3     | msn.com           |

递归 CTE 是 SQLite 中最好的方法。我更喜欢这样的版本:

with cte(id_no, website_link, rest, lev) as (
      select pw.id_no, NULL as website_link, trim(pw.website_link) || ' ' as rest, 1 as lev
      from personal_websessions pw
      union all
      select cte.id_no,
             trim(substr(cte.rest, 1, instr(cte.rest, ' '))),
             substr(cte.rest, instr(cte.rest, ' ') + 1),
             lev + 1
      from cte
      where rest <> '' 
     )
select id_no, website_link
from cte
where website_link <> ''
order by id_no;

Here 是一个 db<>fiddle.

在这个特定版本中,所有字符串操作都在 CTE 的递归部分。主播只是设置数据。

如果 space 是不规则的,使用 trim 可以使查询更健壮——例如,您在其中一个文本值的末尾有一个 space .

至于 lev,我几乎总是将其包含在递归 CTE 中,这样我可以根据需要查看递归的深度。

综上所述,这不是存储数据的好方法。您应该使用一个单独的 table,其结构更像您得到的结果集——每个 id 和唯一网站一行。