【问题标题】:Split values in parts with sqlite使用 sqlite 在部分中拆分值
【发布时间】:2018-09-08 22:51:57
【问题描述】:

我正在努力转换

a | a1,a2,a3
b | b1,b3
c | c2,c1

到:

a | a1
a | a2
a | a3
b | b1
b | b2
c | c2
c | c1

这里是sql格式的数据:

CREATE TABLE data(
  "one"  TEXT,
  "many" TEXT
);
INSERT INTO "data" VALUES('a','a1,a2,a3');
INSERT INTO "data" VALUES('b','b1,b3');
INSERT INTO "data" VALUES('c','c2,c1');

解决方案可能是递归公用表表达式。




这是一个类似于单行的示例:

WITH RECURSIVE list( element, remainder ) AS (
    SELECT NULL AS element, '1,2,3,4,5' AS remainder
        UNION ALL
    SELECT
        CASE
            WHEN INSTR( remainder, ',' )>0 THEN
                SUBSTR( remainder, 0, INSTR( remainder, ',' ) )
            ELSE
                remainder
        END AS element,
        CASE
            WHEN INSTR( remainder, ',' )>0 THEN
                SUBSTR( remainder, INSTR( remainder, ',' )+1 )
            ELSE
                NULL
        END AS remainder
    FROM list
    WHERE remainder IS NOT NULL
)
SELECT * FROM list;

(来自这篇博文:https://blog.expensify.com/2015/09/25/the-simplest-sqlite-common-table-expression-tutorial

它产生:

element | remainder
-------------------
NULL    | 1,2,3,4,5
1       | 2,3,4,5
2       | 3,4,5
3       | 4,5
4       | 5
5       | NULL

因此,问题是将其应用于表中的每一行。

【问题讨论】:

    标签: sqlite common-table-expression recursive-query


    【解决方案1】:

    是的,递归公用表表达式就是解决方案:

    with x(one, firstone, rest) as 
    (select one, substr(many, 1, instr(many, ',')-1) as firstone, substr(many, instr(many, ',')+1) as rest from data where many like "%,%"
       UNION ALL
     select one, substr(rest, 1, instr(rest, ',')-1) as firstone, substr(rest, instr(rest, ',')+1) as rest from x    where rest like "%,%" LIMIT 200
    )
    select one, firstone from x UNION ALL select one, rest from x where rest not like "%,%" 
    ORDER by one;
    

    输出:

    a|a1
    a|a2
    a|a3
    b|b1
    b|b3
    c|c2
    c|c1
    

    【讨论】:

    • 谢谢。为什么limit 200
    • 在执行递归操作时,建议采取额外的预防措施以确保不会以某种无限循环结束(只有专家才能可靠地避免 - 而我没有)。显然,一旦它按要求工作,就可以将其删除。然而,它并没有那么昂贵,以至于使它真正有必要。如果预期的行数较大,则增加该值,或者在您完全确定后将其完全删除。
    【解决方案2】:

    How to split comma-separated value in SQLite? 中查看我的答案。 这将在单个查询中为您提供转换,而不必应用到每一行。

    -- using your data table assuming that b3 is suppose to be b2
    
    WITH split(one, many, str) AS (
        SELECT one, '', many||',' FROM data
        UNION ALL SELECT one,
        substr(str, 0, instr(str, ',')),
        substr(str, instr(str, ',')+1)
        FROM split WHERE str !=''
    ) SELECT one, many FROM split WHERE many!='' ORDER BY one;
    
    a|a1
    a|a2
    a|a3
    b|b1
    b|b2
    c|c2
    c|c1
    

    【讨论】:

      猜你喜欢
      • 2018-03-11
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      • 2021-03-09
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多