Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split a string into rows using pure SQLite

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

Input string:

C:\Users\fidel\Desktop\Temp

and have the query return these rows:

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

In other words, I'd like to split a file path into its constituent paths. Is there a way to do this in pure SQLite?

like image 984
Fidel Avatar asked Jan 07 '16 15:01

Fidel


2 Answers

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.)

like image 186
CL. Avatar answered Oct 17 '22 02:10

CL.


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 ║
╚══════════════════════════════╩══════════════════════════════╩════════════════════════════╩═════╝
like image 9
Lukasz Szozda Avatar answered Oct 17 '22 00:10

Lukasz Szozda