Dalam SQLite, json_tree()
adalah fungsi bernilai tabel yang menjalankan nilai JSON yang diberikan sebagai argumen pertamanya dan mengembalikan tabel yang terdiri dari satu baris untuk setiap elemen larik atau anggota objek.
Kami memberikan nilai JSON sebagai argumen saat kami memanggil fungsi.
Kita dapat secara opsional meneruskan argumen kedua, yang menentukan jalur untuk memulai. Saat kita melakukan ini, json_tree()
memperlakukan jalur tersebut sebagai elemen tingkat atas.
json_tree()
fungsi secara rekursif berjalan melalui substruktur JSON dimulai dengan elemen tingkat atas. Untuk menjalankan hanya turunan langsung dari larik atau objek tingkat atas, atau hanya elemen tingkat atas itu sendiri jika elemen tingkat atas adalah nilai primitif, gunakan json_each()
berfungsi sebagai gantinya.
Sintaks
Kita dapat menggunakan json_tree()
berfungsi dengan cara berikut:
json_tree(X)
json_tree(X,P)
Di mana X
mewakili JSON, dan P
adalah argumen opsional yang mewakili jalur untuk diperlakukan sebagai level teratas.
Contoh
Berikut adalah contoh untuk mendemonstrasikan cara kerjanya:
SELECT * FROM json_tree('{ "name" : "Woof", "age" : 10 }');
Hasil:
+------+--------------------------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+--------------------------+---------+------+----+--------+---------+------+ | null | {"name":"Woof","age":10} | object | null | 0 | null | $ | $ | | name | Woof | text | Woof | 2 | 0 | $.name | $ | | age | 10 | integer | 10 | 4 | 0 | $.age | $ | +------+--------------------------+---------+------+----+--------+---------+------+
Kita dapat melihat bahwa setiap anggota objek memiliki barisnya sendiri dengan beberapa informasi yang berguna, seperti tipenya (nilai teks SQL), jalur, dll.
Tentang id
kolom, menurut dokumentasi SQLite ini adalah nomor rumah tangga internal, yang perhitungannya mungkin berubah di rilis mendatang. Satu-satunya jaminan adalah bahwa id
kolom akan berbeda untuk setiap baris.
Array
Dalam contoh ini, nilai JSON adalah array:
SELECT * FROM json_tree('[ 10, 30, 45 ]');
Hasil:
+------+------------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+------------+---------+------+----+--------+---------+------+ | null | [10,30,45] | array | null | 0 | null | $ | $ | | 0 | 10 | integer | 10 | 1 | 0 | $[0] | $ | | 1 | 30 | integer | 30 | 2 | 0 | $[1] | $ | | 2 | 45 | integer | 45 | 3 | 0 | $[2] | $ | +------+------------+---------+------+----+--------+---------+------+
Tentukan Jalur
Kita dapat menggunakan argumen kedua untuk menentukan jalur yang akan diperlakukan sebagai level teratas.
Contoh:
SELECT * FROM json_tree('{ "a" : 1, "b" : [ 4, 7, 8 ] }', '$.b');
Hasil:
+-----+---------+---------+------+----+--------+---------+------+ | key | value | type | atom | id | parent | fullkey | path | +-----+---------+---------+------+----+--------+---------+------+ | b | [4,7,8] | array | null | 4 | null | $.b | $ | | 0 | 4 | integer | 4 | 5 | 4 | $.b[0] | $.b | | 1 | 7 | integer | 7 | 6 | 4 | $.b[1] | $.b | | 2 | 8 | integer | 8 | 7 | 4 | $.b[2] | $.b | +-----+---------+---------+------+----+--------+---------+------+
Dokumen Lebih Besar
Dalam contoh ini kita akan menggunakan dokumen JSON yang lebih besar. Pertama, panggil json_tree()
tanpa menentukan jalur:
SELECT * FROM json_tree('[
{
"user" : "Spike",
"age" : 30,
"scores" : [ 9, 7, 3 ]
},
{
"user" : "Faye",
"age" : 25,
"scores" : [ 90, 87, 93 ]
},
{
"user" : "Jet",
"age" : 40,
"scores" : [ 50, 38, 67 ]
}
]'
);
Hasil:
+--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | key | value | type | atom | id | parent | fullkey | path | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | null | [{"user":"Spike","age":30,"scores":[9,7,3]},{"user":"Faye"," | array | null | 0 | null | $ | $ | | null | age":25,"scores":[90,87,93]},{"user":"Jet","age":40,"scores | null | null | null | null | null | null | | null | ":[50,38,67]}] | null | null | null | null | null | null | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 0 | {"user":"Spike","age":30,"scores":[9,7,3]} | object | null | 1 | 0 | $[0] | $ | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | user | Spike | text | Spike | 3 | 1 | $[0].user | $[0] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | age | 30 | integer | 30 | 5 | 1 | $[0].age | $[0] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | scores | [9,7,3] | array | null | 7 | 1 | $[0].scores | $[0] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 0 | 9 | integer | 9 | 8 | 7 | $[0].scores[0] | $[0].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 1 | 7 | integer | 7 | 9 | 7 | $[0].scores[1] | $[0].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 2 | 3 | integer | 3 | 10 | 7 | $[0].scores[2] | $[0].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 1 | {"user":"Faye","age":25,"scores":[90,87,93]} | object | null | 11 | 0 | $[1] | $ | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | user | Faye | text | Faye | 13 | 11 | $[1].user | $[1] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | age | 25 | integer | 25 | 15 | 11 | $[1].age | $[1] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | scores | [90,87,93] | array | null | 17 | 11 | $[1].scores | $[1] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 0 | 90 | integer | 90 | 18 | 17 | $[1].scores[0] | $[1].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 1 | 87 | integer | 87 | 19 | 17 | $[1].scores[1] | $[1].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 2 | 93 | integer | 93 | 20 | 17 | $[1].scores[2] | $[1].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 2 | {"user":"Jet","age":40,"scores":[50,38,67]} | object | null | 21 | 0 | $[2] | $ | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | user | Jet | text | Jet | 23 | 21 | $[2].user | $[2] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | age | 40 | integer | 40 | 25 | 21 | $[2].age | $[2] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | scores | [50,38,67] | array | null | 27 | 21 | $[2].scores | $[2] | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 0 | 50 | integer | 50 | 28 | 27 | $[2].scores[0] | $[2].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 1 | 38 | integer | 38 | 29 | 27 | $[2].scores[1] | $[2].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 2 | 67 | integer | 67 | 30 | 27 | $[2].scores[2] | $[2].scores | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+
Dalam hal ini, nilai JSON kami adalah array yang berisi tiga objek. Setiap objek terdaftar dalam hasil, dan setiap anggota objek tersebut terdaftar, bersama dengan nilainya masing-masing, dan seterusnya.
Sekarang, panggil json_tree()
lagi, tapi kali ini kita akan menentukan jalur:
SELECT * FROM json_tree('[
{
"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]'
);
Hasil:
+--------+----------------------------------------------+---------+------+----+--------+----------------+-------------+ | key | value | type | atom | id | parent | fullkey | path | +--------+----------------------------------------------+---------+------+----+--------+----------------+-------------+ | null | {"user":"Faye","age":25,"scores":[90,87,93]} | object | null | 11 | null | $[0] | $ | | user | Faye | text | Faye | 13 | 11 | $[0].user | $[0] | | age | 25 | integer | 25 | 15 | 11 | $[0].age | $[0] | | scores | [90,87,93] | array | null | 17 | 11 | $[0].scores | $[0] | | 0 | 90 | integer | 90 | 18 | 17 | $[0].scores[0] | $[0].scores | | 1 | 87 | integer | 87 | 19 | 17 | $[0].scores[1] | $[0].scores | | 2 | 93 | integer | 93 | 20 | 17 | $[0].scores[2] | $[0].scores | +--------+----------------------------------------------+---------+------+----+--------+----------------+-------------+
Dalam hal ini saya memilih elemen array kedua dengan menentukan [1]
(array berbasis nol di SQLite).
Hasilnya adalah pohon terbatas pada elemen array kedua saja.
Mari kita masuk lebih dalam:
SELECT * FROM json_tree('[
{
"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'
);
Hasil:
+--------+------------+---------+------+----+--------+----------------+-------------+ | key | value | type | atom | id | parent | fullkey | path | +--------+------------+---------+------+----+--------+----------------+-------------+ | scores | [90,87,93] | array | null | 17 | null | $[0].scores | $[0] | | 0 | 90 | integer | 90 | 18 | 17 | $[0].scores[0] | $[0].scores | | 1 | 87 | integer | 87 | 19 | 17 | $[0].scores[1] | $[0].scores | | 2 | 93 | integer | 93 | 20 | 17 | $[0].scores[2] | $[0].scores | +--------+------------+---------+------+----+--------+----------------+-------------+
Semakin dalam kita pergi, semakin sedikit baris yang dikembalikan. Itu karena kami hanya mendapatkan pohon yang dimulai pada jalur spesifik yang kami tentukan.
Memfilter Kueri
Kami dapat memodifikasi kueri kami untuk memfilter hasil berdasarkan kriteria yang diberikan. Misalnya:
SELECT
fullkey,
value
FROM json_tree('[
{
"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_tree.value LIKE '%Faye%';
Hasil:
+-----------+--------------------------------------------------------------+ | fullkey | value | +-----------+--------------------------------------------------------------+ | $ | [{"user":"Spike","age":30,"scores":[9,7,3]},{"user":"Faye"," | | null | age":25,"scores":[90,87,93]},{"user":"Jet","age":40,"scores | | null | ":[50,38,67]}] | +-----------+--------------------------------------------------------------+ | $[1] | {"user":"Faye","age":25,"scores":[90,87,93]} | +-----------+--------------------------------------------------------------+ | $[1].user | Faye | +-----------+--------------------------------------------------------------+
Kita dapat mengembalikan hanya baris terakhir dengan melakukan ini:
SELECT *
FROM json_tree('[
{
"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_tree.value = 'Faye';
Hasil:
+------+-------+------+------+----+--------+-----------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+------+------+----+--------+-----------+------+ | user | Faye | text | Faye | 13 | 11 | $[1].user | $[1] | +------+-------+------+------+----+--------+-----------+------+
Kembalikan Node Daun
Kita dapat membatasi hasilnya hanya pada simpul daun jika kita mau. Dengan "leaf node", maksud saya hanya kunci yang tidak memiliki elemen anak lebih lanjut.
Ada banyak cara melakukan ini.
Salah satu opsi adalah memfilter semua objek dan larik:
SELECT *
FROM json_tree('[
{
"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_tree.type NOT IN ('object','array');
Hasil:
+------+-------+---------+-------+----+--------+----------------+-------------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+---------+-------+----+--------+----------------+-------------+ | user | Spike | text | Spike | 3 | 1 | $[0].user | $[0] | | age | 30 | integer | 30 | 5 | 1 | $[0].age | $[0] | | 0 | 9 | integer | 9 | 8 | 7 | $[0].scores[0] | $[0].scores | | 1 | 7 | integer | 7 | 9 | 7 | $[0].scores[1] | $[0].scores | | 2 | 3 | integer | 3 | 10 | 7 | $[0].scores[2] | $[0].scores | | user | Faye | text | Faye | 13 | 11 | $[1].user | $[1] | | age | 25 | integer | 25 | 15 | 11 | $[1].age | $[1] | | 0 | 90 | integer | 90 | 18 | 17 | $[1].scores[0] | $[1].scores | | 1 | 87 | integer | 87 | 19 | 17 | $[1].scores[1] | $[1].scores | | 2 | 93 | integer | 93 | 20 | 17 | $[1].scores[2] | $[1].scores | | user | Jet | text | Jet | 23 | 21 | $[2].user | $[2] | | age | 40 | integer | 40 | 25 | 21 | $[2].age | $[2] | | 0 | 50 | integer | 50 | 28 | 27 | $[2].scores[0] | $[2].scores | | 1 | 38 | integer | 38 | 29 | 27 | $[2].scores[1] | $[2].scores | | 2 | 67 | integer | 67 | 30 | 27 | $[2].scores[2] | $[2].scores | +------+-------+---------+-------+----+--------+----------------+-------------+
Cara lain untuk melakukannya adalah dengan memeriksa atom
kolom untuk nilai nol. Secara khusus, kami hanya akan mengembalikan baris di mana kolom ini doesn't
berisi nilai nol:
SELECT *
FROM json_tree('[
{
"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 atom IS NOT NULL;
Hasil:
+------+-------+---------+-------+----+--------+----------------+-------------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+---------+-------+----+--------+----------------+-------------+ | user | Spike | text | Spike | 3 | 1 | $[0].user | $[0] | | age | 30 | integer | 30 | 5 | 1 | $[0].age | $[0] | | 0 | 9 | integer | 9 | 8 | 7 | $[0].scores[0] | $[0].scores | | 1 | 7 | integer | 7 | 9 | 7 | $[0].scores[1] | $[0].scores | | 2 | 3 | integer | 3 | 10 | 7 | $[0].scores[2] | $[0].scores | | user | Faye | text | Faye | 13 | 11 | $[1].user | $[1] | | age | 25 | integer | 25 | 15 | 11 | $[1].age | $[1] | | 0 | 90 | integer | 90 | 18 | 17 | $[1].scores[0] | $[1].scores | | 1 | 87 | integer | 87 | 19 | 17 | $[1].scores[1] | $[1].scores | | 2 | 93 | integer | 93 | 20 | 17 | $[1].scores[2] | $[1].scores | | user | Jet | text | Jet | 23 | 21 | $[2].user | $[2] | | age | 40 | integer | 40 | 25 | 21 | $[2].age | $[2] | | 0 | 50 | integer | 50 | 28 | 27 | $[2].scores[0] | $[2].scores | | 1 | 38 | integer | 38 | 29 | 27 | $[2].scores[1] | $[2].scores | | 2 | 67 | integer | 67 | 30 | 27 | $[2].scores[2] | $[2].scores | +------+-------+---------+-------+----+--------+----------------+-------------+
atom
kolom adalah nilai SQL yang sesuai dengan elemen primitif – elemen selain array dan objek JSON. Kolom ini selalu null
untuk larik atau objek JSON. value
kolom sama dengan atom
kolom untuk elemen JSON primitif tetapi mengambil nilai teks JSON untuk array dan objek.
Contoh Basis Data
Misalkan kita memiliki tabel berikut:
SELECT * FROM scores;
Hasil:
+---------+---------------------------------------------------------+ | teacher | students | +---------+---------------------------------------------------------+ | Zohan | [{"Amy":[10,8,9]},{"Josh":[3,2,4]},{"Igor":[7,6,5]}] | | Stacy | [{"Pete":[5,3,1]},{"Liz":[5,8,7]},{"Jet":[9,5,7]}] | | Aisha | [{"Zolton":[4,6,7]},{"Bree":[7,7,4]},{"Rohit":[9,8,8]}] | +---------+---------------------------------------------------------+
Tabel ini disebut scores
memiliki dua kolom. Kolom pertama berisi nama pengajar, dan kolom kedua berisi dokumen JSON. Dokumen JSON berisi siswa dan skor mereka.
Berikut adalah contoh menjalankan kueri yang menggunakan json_tree()
terhadap tabel ini:
SELECT
teacher,
key AS student,
value
FROM
scores,
json_tree(students, '$[1].Liz')
WHERE json_tree.key = 'Liz';
Hasil:
+---------+---------+---------+ | teacher | student | value | +---------+---------+---------+ | Stacy | Liz | [5,8,7] | +---------+---------+---------+
Di sini, kami mengembalikan semua nilai untuk Liz, dan kami juga mengembalikan gurunya.
Kueri berikut mengembalikan skor keduanya:
SELECT
teacher,
key AS student,
value AS score
FROM
scores,
json_tree(students, '$[1].Liz')
WHERE json_tree.key = 1;
Hasil:
+---------+---------+-------+ | teacher | student | score | +---------+---------+-------+ | Stacy | 1 | 8 | +---------+---------+-------+