SQLiteでは、json_tree()
は、最初の引数として提供されたJSON値をウォークし、配列要素またはオブジェクトメンバーごとに1行で構成されるテーブルを返すテーブル値関数です。
オプションで、開始するパスを指定する2番目の引数を渡すことができます。これを行うとき、json_tree()
そのパスを最上位の要素として扱います。
json_tree()
関数は、最上位の要素から始まるJSONサブ構造を再帰的にウォークスルーします。トップレベルの配列またはオブジェクトの直接の子のみ、またはトップレベルの要素がプリミティブ値の場合はトップレベルの要素自体のみをウォークするには、json_each()
を使用します。 代わりに機能します。
json_tree()
を使用できます 次のように機能します:
json_tree(X)
json_tree(X,P)
X
の場所 JSONを表し、P
は、トップレベルとして扱うパスを表すオプションの引数です。
例
SELECT * FROM json_tree('{ "name" : "Woof", "age" : 10 }');
結果:
+------+--------------------------+---------+------+----+--------+---------+------+ | 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 | $ | +------+--------------------------+---------+------+----+--------+---------+------+
各オブジェクトメンバーには、タイプ(SQLテキスト値)やパスなどの有用な情報を含む独自の行があることがわかります。
id
について 列、SQLiteのドキュメントによると、これは内部のハウスキーピング番号であり、その計算は将来のリリースで変更される可能性があります。唯一の保証は、id
列は行ごとに異なります。
配列
この例では、JSON値は配列です:
SELECT * FROM json_tree('[ 10, 30, 45 ]');
結果:
+------+------------+---------+------+----+--------+---------+------+ | 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] | $ | +------+------------+---------+------+----+--------+---------+------+
パスを指定
2番目の引数を使用して、トップレベルとして扱うパスを指定できます。
例:
SELECT * FROM json_tree('{ "a" : 1, "b" : [ 4, 7, 8 ] }', '$.b');
結果:
+-----+---------+---------+------+----+--------+---------+------+ | 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 | +-----+---------+---------+------+----+--------+---------+------+
より大きなドキュメント
この例では、より大きなJSONドキュメントを使用します。まず、json_tree()
を呼び出しましょう パスを指定せずに:
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 ]
}
]'
);
結果:
+--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+ | 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 | +--------+--------------------------------------------------------------+---------+-------+------+--------+----------------+-------------+
この場合、JSON値は3つのオブジェクトを含む配列です。結果には各オブジェクトが一覧表示され、それらの各オブジェクトのメンバーがそれぞれの値とともに一覧表示されます。
それでは、json_tree()
を呼び出しましょう。 繰り返しますが、今回はパスを指定します:
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]'
);
結果:
+--------+----------------------------------------------+---------+------+----+--------+----------------+-------------+ | 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 | +--------+----------------------------------------------+---------+------+----+--------+----------------+-------------+
この場合、[1]
を指定して2番目の配列要素を選択しました (配列はSQLiteに基づいてゼロです。)
その結果、ツリーは2番目の配列要素のみに制限されます。
もっと深く見ていきましょう:
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'
);
結果:
+--------+------------+---------+------+----+--------+----------------+-------------+ | 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 | +--------+------------+---------+------+----+--------+----------------+-------------+
深く進むほど、返される行は少なくなります。これは、指定した特定のパスで始まるツリーのみを取得しているためです。
クエリのフィルタリング
クエリを変更して、特定の基準に基づいて結果をフィルタリングできます。例:
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%';
結果:
+-----------+--------------------------------------------------------------+ | 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 | +-----------+--------------------------------------------------------------+
これを行うことで、最後の行だけを返すことができます:
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';
結果:
+------+-------+------+------+----+--------+-----------+------+ | key | value | type | atom | id | parent | fullkey | path | +------+-------+------+------+----+--------+-----------+------+ | user | Faye | text | Faye | 13 | 11 | $[1].user | $[1] | +------+-------+------+------+----+--------+-----------+------+
リターンリーフノード
必要に応じて、結果をリーフノードのみに制限できます。 「リーフノード」とは、それ以上の子要素を持たないキーのみを意味します。
これを行うにはいくつかの方法があります。
1つのオプションは、すべてのオブジェクトと配列を除外することです。
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');
結果:
+------+-------+---------+-------+----+--------+----------------+-------------+ | 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
をチェックすることです。 null値の列。具体的には、この列がdoesn't
行のみを返します。 null値が含まれています:
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;
結果:
+------+-------+---------+-------+----+--------+----------------+-------------+ | 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
columnは、プリミティブ要素(JSON配列およびオブジェクト以外の要素)に対応するSQL値です。この列は常にnull
JSON配列またはオブジェクトの場合。 value
列はatom
と同じです プリミティブJSON要素の列ですが、配列とオブジェクトのテキストJSON値を取ります。
データベースの例
次の表があるとします。
SELECT * FROM scores;
結果:
+---------+---------------------------------------------------------+ | 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]}] | +---------+---------------------------------------------------------+
このテーブルはscores
と呼ばれます 2つの列があります。最初の列には教師の名前が含まれ、2番目の列にはJSONドキュメントが含まれます。 JSONドキュメントには、学生とそのスコアが含まれています。
json_tree()
を使用するクエリを実行する例を次に示します。 このテーブルに対して:
SELECT
teacher,
key AS student,
value
FROM
scores,
json_tree(students, '$[1].Liz')
WHERE json_tree.key = 'Liz';
結果:
+---------+---------+---------+ | teacher | student | value | +---------+---------+---------+ | Stacy | Liz | [5,8,7] | +---------+---------+---------+
ここでは、リズのすべてのスコアを返し、彼女の先生も返しました。
次のクエリは彼女の2番目のスコアを返します:
SELECT
teacher,
key AS student,
value AS score
FROM
scores,
json_tree(students, '$[1].Liz')
WHERE json_tree.key = 1;
結果:
+---------+---------+-------+ | teacher | student | score | +---------+---------+-------+ | Stacy | 1 | 8 | +---------+---------+-------+