sql >> Base de Datos >  >> RDS >> SQLite

SQLiteJSON_EACH()

En SQLite, json_each() es una función con valores de tabla que recorre el valor JSON proporcionado como su primer argumento y devuelve una tabla que consta de una fila para cada elemento de matriz o miembro de objeto.

Proporcionamos el valor JSON como argumento cuando llamamos a la función.

Opcionalmente, podemos pasar un segundo argumento, que especifica una ruta desde la que empezar. Cuando hacemos esto, json_each() trata esa ruta como el elemento de nivel superior.

El json_each() La función solo recorre los elementos secundarios inmediatos de la matriz u objeto de nivel superior, o solo el elemento de nivel superior en sí mismo si el elemento de nivel superior es un valor primitivo. Para recorrer recursivamente la subestructura JSON, use json_tree() en su lugar.

Sintaxis

Podemos usar la función de las siguientes formas:

json_each(X)
json_each(X,P)

Donde X representa el JSON y P es un argumento opcional que representa la ruta a tratar como de nivel superior.

Ejemplo

Aquí hay un ejemplo para demostrar cómo funciona:

SELECT * FROM json_each('{ "name" : "Woof", "age" : 10 }');

Resultado:

+------+-------+---------+------+----+--------+---------+------+
| key  | value |  type   | atom | id | parent | fullkey | path |
+------+-------+---------+------+----+--------+---------+------+
| name | Woof  | text    | Woof | 2  | null   | $.name  | $    |
| age  | 10    | integer | 10   | 4  | null   | $.age   | $    |
+------+-------+---------+------+----+--------+---------+------+

Podemos ver que cada miembro del objeto tiene su propia fila con información útil, como su tipo (valor de texto SQL), ruta, etc.

Con respecto al id columna, de acuerdo con la documentación de SQLite, este es un número de mantenimiento interno, cuyo cálculo podría cambiar en versiones futuras. La única garantía es que el id la columna será diferente para cada fila.

La columna principal siempre es null al llamar a json_each() . Esta columna se vuelve más significativa cuando se usa json_tree() .

Matriz

En este ejemplo, el valor JSON es una matriz:

SELECT * FROM json_each('[ 10, 30, 45 ]');

Resultado:

+-----+-------+---------+------+----+--------+---------+------+
| key | value |  type   | atom | id | parent | fullkey | path |
+-----+-------+---------+------+----+--------+---------+------+
| 0   | 10    | integer | 10   | 1  | null   | $[0]    | $    |
| 1   | 30    | integer | 30   | 2  | null   | $[1]    | $    |
| 2   | 45    | integer | 45   | 3  | null   | $[2]    | $    |
+-----+-------+---------+------+----+--------+---------+------+

Especifique una ruta

Podemos usar un segundo argumento para especificar una ruta para tratar como el nivel superior.

Ejemplo:

SELECT * FROM json_each('{ "a" : 1, "b" : [ 4, 7, 8 ] }', '$.b');

Resultado:

+-----+-------+---------+------+----+--------+---------+------+
| key | value |  type   | atom | id | parent | fullkey | path |
+-----+-------+---------+------+----+--------+---------+------+
| 0   | 4     | integer | 4    | 5  | null   | $.b[0]  | $.b  |
| 1   | 7     | integer | 7    | 6  | null   | $.b[1]  | $.b  |
| 2   | 8     | integer | 8    | 7  | null   | $.b[2]  | $.b  |
+-----+-------+---------+------+----+--------+---------+------+

Documento más grande

En este ejemplo, usaremos un documento JSON más grande. Primero, llamemos a json_each() sin especificar una ruta:

SELECT * FROM json_each('[
        { 
        "user" : "Spike",
        "age" : 30,
        "scores" : [ 9, 7, 3 ]
        },
        { 
        "user" : "Faye",
        "age" : 25,
        "scores" : [ 90, 87, 93 ]
        },
        { 
        "user" : "Jet",
        "age" : 40,
        "scores" : [ 50, 38, 67 ]
        }
        ]'
    );

Resultado:

+-----+----------------------------------------------+--------+------+----+--------+---------+------+
| key |                    value                     |  type  | atom | id | parent | fullkey | path |
+-----+----------------------------------------------+--------+------+----+--------+---------+------+
| 0   | {"user":"Spike","age":30,"scores":[9,7,3]}   | object | N/A  | 1  | N/A    | $[0]    | $    |
| 1   | {"user":"Faye","age":25,"scores":[90,87,93]} | object | N/A  | 11 | N/A    | $[1]    | $    |
| 2   | {"user":"Jet","age":40,"scores":[50,38,67]}  | object | N/A  | 21 | N/A    | $[2]    | $    |
+-----+----------------------------------------------+--------+------+----+--------+---------+------+

En este caso, nuestro valor JSON es una matriz que contiene tres objetos. Cada objeto se enumera en los resultados.

Ahora, llamemos a json_each() de nuevo, pero esta vez especificaremos una ruta:

SELECT * FROM json_each('[
        { 
        "user" : "Spike",
        "age" : 30,
        "scores" : [ 9, 7, 3 ]
        },
        { 
        "user" : "Faye",
        "age" : 25,
        "scores" : [ 90, 87, 93 ]
        },
        { 
        "user" : "Jet",
        "age" : 40,
        "scores" : [ 50, 38, 67 ]
        }
        ]',
        '$[1]'
    );

Resultado:

+--------+------------+---------+------+----+--------+-------------+------+
|  key   |   value    |  type   | atom | id | parent |   fullkey   | path |
+--------+------------+---------+------+----+--------+-------------+------+
| user   | Faye       | text    | Faye | 13 | null   | $[1].user   | $[1] |
| age    | 25         | integer | 25   | 15 | null   | $[1].age    | $[1] |
| scores | [90,87,93] | array   | null | 17 | null   | $[1].scores | $[1] |
+--------+------------+---------+------+----+--------+-------------+------+

En este caso, elegí el segundo elemento de la matriz especificando [1] (las matrices están basadas en cero en SQLite).

El resultado es que la salida contiene información sobre el segundo elemento de la matriz.

Esta vez podemos ver que la path la columna contiene $[1] .

Profundicemos:

SELECT * FROM json_each('[
        { 
        "user" : "Spike",
        "age" : 30,
        "scores" : [ 9, 7, 3 ]
        },
        { 
        "user" : "Faye",
        "age" : 25,
        "scores" : [ 90, 87, 93 ]
        },
        { 
        "user" : "Jet",
        "age" : 40,
        "scores" : [ 50, 38, 67 ]
        }
        ]',
        '$[1].scores'
    );

Resultado:

+-----+-------+---------+------+----+--------+----------------+-------------+
| key | value |  type   | atom | id | parent |    fullkey     |    path     |
+-----+-------+---------+------+----+--------+----------------+-------------+
| 0   | 90    | integer | 90   | 18 | null   | $[1].scores[0] | $[1].scores |
| 1   | 87    | integer | 87   | 19 | null   | $[1].scores[1] | $[1].scores |
| 2   | 93    | integer | 93   | 20 | null   | $[1].scores[2] | $[1].scores |
+-----+-------+---------+------+----+--------+----------------+-------------+

Ahora obtenemos una fila para cada elemento en las scores matriz.

Filtrado de la consulta

Podemos modificar nuestra consulta para filtrar los resultados en función de un criterio dado. Por ejemplo:

SELECT 
    fullkey, 
    value 
FROM json_each('[
        { 
        "user" : "Spike",
        "age" : 30,
        "scores" : [ 9, 7, 3 ]
        },
        { 
        "user" : "Faye",
        "age" : 25,
        "scores" : [ 90, 87, 93 ]
        },
        { 
        "user" : "Jet",
        "age" : 40,
        "scores" : [ 50, 38, 67 ]
        }
        ]'
    )
WHERE json_each.value LIKE '%Faye%';

Resultado:

+---------+----------------------------------------------+
| fullkey |                    value                     |
+---------+----------------------------------------------+
| $[1]    | {"user":"Faye","age":25,"scores":[90,87,93]} |
+---------+----------------------------------------------+

Un ejemplo de base de datos

Supongamos que tenemos la siguiente tabla:

SELECT * FROM guests;

Resultado:

+-------+--------------------------------------------------+
| guest |                      lunch                       |
+-------+--------------------------------------------------+
| Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"]       |
| Amy   | ["Vegetable Quiche", "Apple", "Fruit Juice"]     |
| Rohit | ["Beef Curry", "Dragonfruit", "Vegetable Juice"] |
| Igor  | ["Chicken Pie", "Jackfruit", "Fruit Juice"]      |
| Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"]  |
| Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"]    |
+-------+--------------------------------------------------+

Esta tabla se llama guests tiene dos columnas. La primera columna contiene el nombre del invitado y la segunda columna contiene su orden de almuerzo. Pueden pedir tres platos para el almuerzo. Su orden de almuerzo tiene la forma de una matriz, donde cada plato es un elemento de la matriz.

Aquí hay un ejemplo de cómo ejecutar una consulta que incorpora json_each() contra esta mesa:

SELECT DISTINCT
    guest,
    lunch
FROM 
    guests, 
    json_each(lunch)
WHERE json_each.value LIKE 'Apple Juice';

Resultado:

+-------+-------------------------------------------------+
| guest |                      lunch                      |
+-------+-------------------------------------------------+
| Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"]      |
| Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] |
| Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"]   |
+-------+-------------------------------------------------+

Aquí, devolvimos a todos los invitados que ordenaron jugo de manzana con su almuerzo, junto con su pedido de almuerzo completo.

Si queremos devolver a todos los invitados que pidieron "algo" de manzana, podríamos hacer esto:

SELECT DISTINCT
    guest,
    lunch
FROM 
    guests, 
    json_each(lunch)
WHERE json_each.value LIKE 'Apple%';

Resultado:

+-------+-------------------------------------------------+
| guest |                      lunch                      |
+-------+-------------------------------------------------+
| Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"]      |
| Amy   | ["Vegetable Quiche", "Apple", "Fruit Juice"]    |
| Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] |
| Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"]   |
+-------+-------------------------------------------------+

Note que usé el DISTINCT cláusula en mi consulta. Esto asegura que no obtengamos múltiples filas para el mismo invitado. Para demostrar lo que quiero decir, aquí está la consulta de nuevo, pero sin DISTINCT cláusula:

SELECT
    guest,
    lunch
FROM 
    guests, 
    json_each(lunch)
WHERE json_each.value LIKE 'Apple%';

Resultado:

+-------+-------------------------------------------------+
| guest |                      lunch                      |
+-------+-------------------------------------------------+
| Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"]      |
| Amy   | ["Vegetable Quiche", "Apple", "Fruit Juice"]    |
| Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] |
| Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"]   |
| Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"]   |
+-------+-------------------------------------------------+

Esta vez Aisha aparece dos veces. Eso es porque pidió dos platos de manzana para el almuerzo:pastel de manzana y jugo de manzana.