从 JSON 个对象数组中提取特定对象值的数据
Extracting data from an array of JSON objects for specific object values
在我的 table 中,有一个 JSON
类型的列,其中包含一个描述时间偏移的对象数组:
[
{
"type": "start"
"time": 1.234
},
{
"type": "end"
"time": 50.403
}
]
我知道我可以用 JSON_EACH()
和 JSON_EXTRACT()
:
提取这些
CREATE TEMPORARY TABLE Items(
id INTEGER PRIMARY KEY,
timings JSON
);
INSERT INTO Items(timings) VALUES
('[{"type": "start", "time": 12.345}, {"type": "end", "time": 67.891}]'),
('[{"type": "start", "time": 24.56}, {"type": "end", "time": 78.901}]');
SELECT
JSON_EXTRACT(Timings.value, '$.type'),
JSON_EXTRACT(Timings.value, '$.time')
FROM
Items,
JSON_EACH(timings) AS Timings;
这个returns一个table喜欢:
start 12.345
end 67.891
start 24.56
end 78.901
我真正需要的是:
- 查找特定类型的时间。 (找到数组中第一个符合条件的对象。)
- 将此数据 select 与其余 table 作为一列。
换句话说,我正在寻找像这样的 table:
id start end
-----------------------------
0 12.345 67.891
1 24.56 78.901
我希望得到这样的查询:
SELECT
id,
JSON_EXTRACT(timings, '$.[type="start"].time'),
JSON_EXTRACT(timings, '$.[type="end"].time')
FROM Items;
有什么方法可以使用 JSON 函数中的路径来 select 我需要的东西吗?或者,以其他方式将第一个示例中的内容应用于 table?
一种可能:
WITH cte(id, json) AS
(SELECT Items.id
, json_group_object(json_extract(j.value, '$.type'), json_extract(j.value, '$.time'))
FROM Items
JOIN json_each(timings) AS j ON json_extract(j.value, '$.type') IN ('start', 'end')
GROUP BY Items.id)
SELECT id
, json_extract(json, '$.start') AS start
, json_extract(json, '$.end') AS "end"
FROM cte
ORDER BY id;
这给出了
id start end
---------- ---------- ----------
1 12.345 67.891
2 24.56 78.901
另一个使用 sqlite 3.25 中添加的 window 函数并避免创建中间 JSON 对象:
SELECT DISTINCT Items.id
, max(json_extract(j.value, '$.time'))
FILTER (WHERE json_extract(j.value, '$.type') = 'start') OVER ids AS start
, max(json_extract(j.value, '$.time'))
FILTER (WHERE json_extract(j.value, '$.type') = 'end') OVER ids AS "end"
FROM Items
JOIN json_each(timings) AS j ON json_extract(j.value, '$.type') IN ('start', 'end')
WINDOW ids AS (PARTITION BY Items.id)
ORDER BY Items.id;
关键是使用 JOIN
的 ON
子句将结果限制为您关心的每个数组中的两个对象,然后将每个对象最多合并两行 Items.id
通过几种不同的方法合二为一。
在我的 table 中,有一个 JSON
类型的列,其中包含一个描述时间偏移的对象数组:
[
{
"type": "start"
"time": 1.234
},
{
"type": "end"
"time": 50.403
}
]
我知道我可以用 JSON_EACH()
和 JSON_EXTRACT()
:
CREATE TEMPORARY TABLE Items(
id INTEGER PRIMARY KEY,
timings JSON
);
INSERT INTO Items(timings) VALUES
('[{"type": "start", "time": 12.345}, {"type": "end", "time": 67.891}]'),
('[{"type": "start", "time": 24.56}, {"type": "end", "time": 78.901}]');
SELECT
JSON_EXTRACT(Timings.value, '$.type'),
JSON_EXTRACT(Timings.value, '$.time')
FROM
Items,
JSON_EACH(timings) AS Timings;
这个returns一个table喜欢:
start 12.345
end 67.891
start 24.56
end 78.901
我真正需要的是:
- 查找特定类型的时间。 (找到数组中第一个符合条件的对象。)
- 将此数据 select 与其余 table 作为一列。
换句话说,我正在寻找像这样的 table:
id start end
-----------------------------
0 12.345 67.891
1 24.56 78.901
我希望得到这样的查询:
SELECT
id,
JSON_EXTRACT(timings, '$.[type="start"].time'),
JSON_EXTRACT(timings, '$.[type="end"].time')
FROM Items;
有什么方法可以使用 JSON 函数中的路径来 select 我需要的东西吗?或者,以其他方式将第一个示例中的内容应用于 table?
一种可能:
WITH cte(id, json) AS
(SELECT Items.id
, json_group_object(json_extract(j.value, '$.type'), json_extract(j.value, '$.time'))
FROM Items
JOIN json_each(timings) AS j ON json_extract(j.value, '$.type') IN ('start', 'end')
GROUP BY Items.id)
SELECT id
, json_extract(json, '$.start') AS start
, json_extract(json, '$.end') AS "end"
FROM cte
ORDER BY id;
这给出了
id start end
---------- ---------- ----------
1 12.345 67.891
2 24.56 78.901
另一个使用 sqlite 3.25 中添加的 window 函数并避免创建中间 JSON 对象:
SELECT DISTINCT Items.id
, max(json_extract(j.value, '$.time'))
FILTER (WHERE json_extract(j.value, '$.type') = 'start') OVER ids AS start
, max(json_extract(j.value, '$.time'))
FILTER (WHERE json_extract(j.value, '$.type') = 'end') OVER ids AS "end"
FROM Items
JOIN json_each(timings) AS j ON json_extract(j.value, '$.type') IN ('start', 'end')
WINDOW ids AS (PARTITION BY Items.id)
ORDER BY Items.id;
关键是使用 JOIN
的 ON
子句将结果限制为您关心的每个数组中的两个对象,然后将每个对象最多合并两行 Items.id
通过几种不同的方法合二为一。