W SQLite, json_each()
to funkcja z wartościami przechowywanymi w tabeli, która przeszukuje wartość JSON podaną jako pierwszy argument i zwraca tabelę składającą się z jednego wiersza dla każdego elementu tablicy lub elementu obiektu.
Podajemy wartość JSON jako argument, gdy wywołujemy funkcję.
Opcjonalnie możemy przekazać drugi argument, który określa ścieżkę startową. Kiedy to zrobimy, json_each()
traktuje tę ścieżkę jako element najwyższego poziomu.
json_each()
function przeszukuje tylko bezpośrednie elementy podrzędne tablicy lub obiektu najwyższego poziomu lub tylko sam element najwyższego poziomu, jeśli element najwyższego poziomu jest wartością pierwotną. Aby rekursywnie przechodzić przez podstrukturę JSON, użyj json_tree()
zamiast tego.
Składnia
Możemy korzystać z funkcji w następujący sposób:
json_each(X)
json_each(X,P)
Gdzie X
reprezentuje JSON, a P
jest opcjonalnym argumentem, który reprezentuje ścieżkę, którą należy traktować jako najwyższy poziom.
Przykład
Oto przykład pokazujący, jak to działa:
SELECT * FROM json_each('{ "name" : "Woof", "age" : 10 }');
Wynik:
+------+-------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+---------+------+----+--------+---------+------+ | name | Woof | text | Woof | 2 | null | $.name | $ | | age | 10 | integer | 10 | 4 | null | $.age | $ | +------+-------+---------+------+----+--------+---------+------+
Widzimy, że każdy element obiektu ma swój własny wiersz z przydatnymi informacjami, takimi jak typ (wartość tekstowa SQL), ścieżka itp.
Odnośnie id
kolumna, zgodnie z dokumentacją SQLite jest to wewnętrzny numer porządkowy, którego obliczenia mogą ulec zmianie w przyszłych wydaniach. Jedyną gwarancją jest to, że id
kolumna będzie inna dla każdego wiersza.
Kolumna nadrzędna jest zawsze null
podczas wywoływania json_each()
. Ta kolumna staje się bardziej znacząca, gdy używasz json_tree()
.
Tablica
W tym przykładzie wartość JSON jest tablicą:
SELECT * FROM json_each('[ 10, 30, 45 ]');
Wynik:
+-----+-------+---------+------+----+--------+---------+------+ | 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] | $ | +-----+-------+---------+------+----+--------+---------+------+
Określ ścieżkę
Możemy użyć drugiego argumentu, aby określić ścieżkę, która będzie traktowana jako najwyższy poziom.
Przykład:
SELECT * FROM json_each('{ "a" : 1, "b" : [ 4, 7, 8 ] }', '$.b');
Wynik:
+-----+-------+---------+------+----+--------+---------+------+ | 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 | +-----+-------+---------+------+----+--------+---------+------+
Większy dokument
W tym przykładzie użyjemy większego dokumentu JSON. Najpierw wywołajmy json_each()
bez określania ścieżki:
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 ]
}
]'
);
Wynik:
+-----+----------------------------------------------+--------+------+----+--------+---------+------+ | 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] | $ | +-----+----------------------------------------------+--------+------+----+--------+---------+------+
W tym przypadku naszą wartością JSON jest tablica zawierająca trzy obiekty. Każdy obiekt jest wymieniony w wynikach.
Teraz wywołajmy json_each()
ponownie, ale tym razem określimy ścieżkę:
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]'
);
Wynik:
+--------+------------+---------+------+----+--------+-------------+------+ | 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] | +--------+------------+---------+------+----+--------+-------------+------+
W tym przypadku wybrałem drugi element tablicy, określając [1]
(tablice mają wartość zero w SQLite).
W rezultacie dane wyjściowe zawierają informacje o drugim elemencie tablicy.
Tym razem widzimy, że path
kolumna zawiera $[1]
.
Przejdźmy głębiej:
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'
);
Wynik:
+-----+-------+---------+------+----+--------+----------------+-------------+ | 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 | +-----+-------+---------+------+----+--------+----------------+-------------+
Teraz otrzymujemy wiersz dla każdego elementu w scores
tablica.
Filtrowanie zapytania
Możemy zmodyfikować nasze zapytanie, aby filtrować wyniki na podstawie podanych kryteriów. Na przykład:
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%';
Wynik:
+---------+----------------------------------------------+ | fullkey | value | +---------+----------------------------------------------+ | $[1] | {"user":"Faye","age":25,"scores":[90,87,93]} | +---------+----------------------------------------------+
Przykład bazy danych
Załóżmy, że mamy następującą tabelę:
SELECT * FROM guests;
Wynik:
+-------+--------------------------------------------------+ | 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"] | +-------+--------------------------------------------------+
Ta tabela nazywa się guests
ma dwie kolumny. Pierwsza kolumna zawiera nazwisko gościa, a druga zawiera jego zamówienie na lunch. Na obiad można zamówić trzy dania. Ich zamówienie na lunch ma postać tablicy, w której każde danie jest elementem tablicy.
Oto przykład uruchomienia zapytania, które zawiera json_each()
w stosunku do tej tabeli:
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple Juice';
Wynik:
+-------+-------------------------------------------------+ | guest | lunch | +-------+-------------------------------------------------+ | Zohan | ["Beef Pie", "Fruit Salad", "Apple Juice"] | | Stacy | ["Chicken Curry", "Fruit Salad", "Apple Juice"] | | Aisha | ["Chicken Curry", "Apple Pie", "Apple Juice"] | +-------+-------------------------------------------------+
Tutaj zwróciliśmy wszystkim gościom, którzy zamówili sok jabłkowy do lunchu, wraz z ich pełnym zamówieniem na lunch.
Jeśli chcemy zwrócić wszystkim gościom, którzy zamówili jabłkowe „coś”, możemy to zrobić:
SELECT DISTINCT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Wynik:
+-------+-------------------------------------------------+ | 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"] | +-------+-------------------------------------------------+
Zauważ, że użyłem DISTINCT
klauzula w moim zapytaniu. Dzięki temu nie otrzymamy wielu wierszy zwróconych dla tego samego gościa. Aby zademonstrować, co mam na myśli, oto zapytanie ponownie, ale bez DISTINCT
klauzula:
SELECT
guest,
lunch
FROM
guests,
json_each(lunch)
WHERE json_each.value LIKE 'Apple%';
Wynik:
+-------+-------------------------------------------------+ | 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"] | +-------+-------------------------------------------------+
Tym razem Aisha pojawia się dwukrotnie. To dlatego, że na lunch zamówiła dwa jabłka – szarlotkę i sok jabłkowy.