Split a string into rows using pure SQLite

前端 未结 4 1415
深忆病人
深忆病人 2020-12-16 06:08

Using SQLite, I\'d like to split a string in the following way.

Input string:

C:\\Users\\fidel\\Desktop\\Temp

and have

相关标签:
4条回答
  • 2020-12-16 06:13

    Recursive CTE:

    WITH RECURSIVE cte(org, part, rest, pos) AS (
      VALUES('C:\Users\fidel\Desktop\Temp', '','C:\Users\fidel\Desktop\Temp'|| '\', 0)
      UNION ALL
      SELECT org,
             SUBSTR(org,1, pos + INSTR(rest, '\')),
             SUBSTR(rest, INSTR(rest, '\')+1),
             pos + INSTR(rest, '\')
      FROM cte
      WHERE INSTR(rest, '\') > 0                         
    )
    SELECT *
    FROM cte
    WHERE pos <> 0
    ORDER BY pos; 
    

    SqlFiddleDemo

    Output:

    ╔═════════════════════════════╗
    ║            part             ║
    ╠═════════════════════════════╣
    ║ C:\                         ║
    ║ C:\Users\                   ║
    ║ C:\Users\fidel\             ║
    ║ C:\Users\fidel\Desktop\     ║
    ║ C:\Users\fidel\Desktop\Temp ║
    ╚═════════════════════════════╝
    

    How it works:

    org  - original string does not change
    part - simply `LEFT` equivalent of original string taking pos number of chars
    rest - simply `RIGHT` equivalent, rest of org string
    pos  - position of first `\` in the rest 
    

    Trace:

    ╔══════════════════════════════╦══════════════════════════════╦════════════════════════════╦═════╗
    ║             org              ║            part              ║           rest             ║ pos ║
    ╠══════════════════════════════╬══════════════════════════════╬════════════════════════════╬═════╣
    ║ C:\Users\fidel\Desktop\Temp  ║ C:\                          ║ Users\fidel\Desktop\Temp\  ║   3 ║
    ║ C:\Users\fidel\Desktop\Temp  ║ C:\Users\                    ║ fidel\Desktop\Temp\        ║   9 ║
    ║ C:\Users\fidel\Desktop\Temp  ║ C:\Users\fidel\              ║ Desktop\Temp\              ║  15 ║
    ║ C:\Users\fidel\Desktop\Temp  ║ C:\Users\fidel\Desktop\      ║ Temp\                      ║  23 ║
    ║ C:\Users\fidel\Desktop\Temp  ║ C:\Users\fidel\Desktop\Temp  ║                            ║  28 ║
    ╚══════════════════════════════╩══════════════════════════════╩════════════════════════════╩═════╝
    
    0 讨论(0)
  • 2020-12-16 06:16

    If you want to search for the values ​​individually, use the code below:

    WITH RECURSIVE split(content, last, rest) AS (
    VALUES('', '', 'value1§value2§value3§value4§value5§value6§value7')
    UNION ALL
      SELECT 
    
        CASE WHEN last = '§' 
                THEN
                    substr(rest, 1, 1)
                ELSE
                    content || substr(rest, 1, 1)
        END,
         substr(rest, 1, 1),
         substr(rest, 2)
      FROM split
      WHERE rest <> ''
    )
    SELECT 
           REPLACE(content, '§','') AS 'ValueSplit'     
    FROM 
           split
    WHERE 
           last = '§' OR rest ='';
    

    Result:

    **ValueSplit**
    
    value1
    value2
    value3
    value4
    value5
    value6
    value7
    

    I hope I can help people with the same problem.

    0 讨论(0)
  • 2020-12-16 06:27

    This is possible with a recursive common table expression:

    WITH RECURSIVE split(s, last, rest) AS (
      VALUES('', '', 'C:\Users\fidel\Desktop\Temp')
      UNION ALL
      SELECT s || substr(rest, 1, 1),
             substr(rest, 1, 1),
             substr(rest, 2)
      FROM split
      WHERE rest <> ''
    )
    SELECT s
    FROM split
    WHERE rest = ''
       OR last = '\';
    

    (You did not ask for a reasonable way.)

    0 讨论(0)
  • 2020-12-16 06:31

    Inspired from Lukasz Szozda's answer:

     WITH RECURSIVE cte("pre","post") AS (   
       VALUES('C:', 'Users\fidel\Desktop\Temp' || '\')
     UNION ALL
       SELECT "pre" || '\' || left("post",     position('\' in "post")-1),
                         substring("post" from position('\' in "post")+1)
       FROM cte   
       WHERE "post" > ''                             
     ) 
     SELECT "pre" FROM cte
    

    (tested on PostgreSQL)

    The idea is now to replace the VALUES line

    VALUES('C:', 'Users\fidel\Desktop\Temp' || '\')
    

    with placeholders like

     VALUES(?, ? || '\')
    

    which have been pre-split in the programming language that is going to run the SQL statement above against the data base.

    Reading the SQLite docs, I see that substring(... from ...) has to be replaced by substr(..., ...) and position(... in ...) is to be replaced by instr(..., ...) with parameters swapped.

    Very annoying for me since I wanted SQL code that runs on both PostgreSQL and SQLite.

    0 讨论(0)
提交回复
热议问题