SQLite
 sql >> Database >  >> RDS >> SQLite

SQLite JSON_EACH()

In SQLite, json_each() è una funzione con valori di tabella che esamina il valore JSON fornito come primo argomento e restituisce una tabella composta da una riga per ogni elemento dell'array o membro dell'oggetto.

Forniamo il valore JSON come argomento quando chiamiamo la funzione.

Possiamo opzionalmente passare un secondo argomento, che specifica un percorso da cui partire. Quando lo facciamo, json_each() considera quel percorso come l'elemento di primo livello.

Il json_each() la funzione percorre solo i figli immediati dell'array o dell'oggetto di livello superiore, o solo l'elemento di livello superiore stesso se l'elemento di livello superiore è un valore primitivo. Per scorrere in modo ricorsivo la sottostruttura JSON, utilizza json_tree() invece.

Sintassi

Possiamo utilizzare la funzione nei seguenti modi:

json_each(X)
json_each(X,P)

Dove X rappresenta il JSON e P è un argomento facoltativo che rappresenta il percorso da considerare come di livello superiore.

Esempio

Ecco un esempio per dimostrare come funziona:

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

Risultato:

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

Possiamo vedere che ogni membro dell'oggetto ha una propria riga con alcune informazioni utili, come il tipo (valore del testo SQL), il percorso, ecc.

Per quanto riguarda l'id colonna, secondo la documentazione di SQLite si tratta di un numero di pulizia interno, il cui calcolo potrebbe cambiare nelle versioni future. L'unica garanzia è che l'id la colonna sarà diversa per ogni riga.

La colonna principale è sempre null quando si chiama json_each() . Questa colonna diventa più significativa quando si utilizza json_tree() .

Matrice

In questo esempio, il valore JSON è un array:

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

Risultato:

+-----+-------+---------+------+----+--------+---------+------+
| 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]    | $    |
+-----+-------+---------+------+----+--------+---------+------+

Specifica un percorso

Possiamo usare un secondo argomento per specificare un percorso da trattare come di livello superiore.

Esempio:

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

Risultato:

+-----+-------+---------+------+----+--------+---------+------+
| 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 più grande

In questo esempio useremo un documento JSON più grande. Per prima cosa, chiamiamo json_each() senza specificare un percorso:

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 ]
        }
        ]'
    );

Risultato:

+-----+----------------------------------------------+--------+------+----+--------+---------+------+
| 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]    | $    |
+-----+----------------------------------------------+--------+------+----+--------+---------+------+

In questo caso, il nostro valore JSON è un array che contiene tre oggetti. Ogni oggetto è elencato nei risultati.

Ora chiamiamo json_each() di nuovo, ma questa volta specificheremo un percorso:

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]'
    );

Risultato:

+--------+------------+---------+------+----+--------+-------------+------+
|  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] |
+--------+------------+---------+------+----+--------+-------------+------+

In questo caso ho scelto il secondo elemento dell'array specificando [1] (gli array sono basati su zero in SQLite).

Il risultato è che l'output contiene informazioni sul secondo elemento dell'array.

Questa volta possiamo vedere che il path la colonna contiene $[1] .

Andiamo più a fondo:

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'
    );

Risultato:

+-----+-------+---------+------+----+--------+----------------+-------------+
| 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 |
+-----+-------+---------+------+----+--------+----------------+-------------+

Ora otteniamo una riga per ogni elemento nei scores matrice.

Filtraggio della query

Possiamo modificare la nostra query per filtrare i risultati in base a un determinato criterio. Ad esempio:

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%';

Risultato:

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

Un esempio di database

Supponiamo di avere la seguente tabella:

SELECT * FROM guests;

Risultato:

+-------+--------------------------------------------------+
| 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"]    |
+-------+--------------------------------------------------+

Questa tabella chiamata guests ha due colonne. La prima colonna contiene il nome dell'ospite e la seconda colonna contiene l'ordine del pranzo. Possono ordinare tre piatti per pranzo. Il loro ordine per il pranzo è sotto forma di una matrice, in cui ogni piatto è un elemento della matrice.

Ecco un esempio di esecuzione di una query che incorpora json_each() contro questa tabella:

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

Risultato:

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

Qui, abbiamo restituito tutti gli ospiti che hanno ordinato il succo di mela con il loro pranzo, insieme al loro ordine completo per il pranzo.

Se vogliamo restituire tutti gli ospiti che hanno ordinato "qualcosa" di Apple, potremmo farlo:

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

Risultato:

+-------+-------------------------------------------------+
| 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"]   |
+-------+-------------------------------------------------+

Nota che ho usato il DISTINCT clausola nella mia domanda. Ciò garantisce che non vengano restituite più righe per lo stesso ospite. Per dimostrare cosa intendo, ecco di nuovo la query, ma senza DISTINCT clausola:

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

Risultato:

+-------+-------------------------------------------------+
| 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"]   |
+-------+-------------------------------------------------+

Questa volta Aisha appare due volte. Questo perché ha ordinato due piatti di mele per pranzo:torta di mele e succo di mela.