4

I'm using DB Manager on QGIS to write a view. I want to "translate" unnest() SQL function, but I don't find the same in SQLite.

SQL

SELECT unnest(ARRAY['A','B','C']);
unnest
A
B
C

The documentation describes two aggregate functions and two table-valued functions. I tried json_each, which returns a row for each json value but I can't display unnested values.

SQLite

SELECT myfield
FROM my_table, json_each(my_field);
my_field
["A", "B", "C" ]
["A", "B", "C" ]
["A", "B", "C" ]

How to easily unnest json elements in SQLite?

4
  • 1
    Only way is a recursive CTE: gis.stackexchange.com/a/460107/93656
    – geozelot
    May 31 at 14:09
  • 1
    In SQLite there is no such function: unnest
    – GeoGyro
    May 31 at 14:12
  • If you are referring to the unnest in my linked answer, that's not a function but a virtual table name of the recursive CTE expresion that mimics an unnest. However, you may want to try the json_tree variant to also walk children. If that doesn't unnest the array values of your JSON, you have to use the recursive CTE as in my linked answer. And you will have to use the recursive CTE if your array is not a valid JSON in the first place...
    – geozelot
    May 31 at 14:26
  • Ok, understand.
    – GeoGyro
    May 31 at 15:11

2 Answers 2

5

As @geozelot suggests, the only way I found is a recursive CTE.

WITH RECURSIVE
  unnest(val, arr_el, _arr_res) AS (
    SELECT
      myfield,
      '',
      myfield || ','
    FROM
      my_table
    UNION ALL
    SELECT
      val,
      SUBSTR(_arr_res, 0, INSTR(_arr_res, ',')),
      SUBSTR(_arr_res, INSTR(_arr_res, ',') + 1)
    FROM
      unnest
    WHERE
      _arr_res <> ''
  )
SELECT
  REPLACE(REPLACE(REPLACE(arr_el, '[', ''), ']', ''), '"', '') AS arr_el,
  val
FROM
  unnest
WHERE
  arr_el <> ''
ORDER BY
  val, arr_el
;

Really heavy to manipulate, I'm surprised there are aggregates functions and no easy way to disaggregate.

2

The json_each function returns the desired values in the value column:

create table my_table(id, myfield);
insert into my_table values (1, '["A","B","C"]'), (2, '["X"]');

SELECT my_table.id, j.value
FROM my_table, json_each(myfield) j;
id | value
----------
1  | A
1  | B
1  | C
2  | X
1
  • Great, exactly what I was looking for.
    – GeoGyro
    Jun 1 at 8:33

Not the answer you're looking for? Browse other questions tagged or ask your own question.