在我的表格中,有一列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;
这将返回一个表,如:
start 12.345
end 67.891
start 24.56
end 78.901
我真正需要的是:
换句话说,我正在寻找一个看起来像这样的表:
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函数中的path来选择我需要的方法?或者,采用其他方法来枢转第一个示例中应用于表的内容?
答案 0 :(得分:1)
一种可能性:
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中添加的窗口函数并避免创建中间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;
关键是使用ON
的{{1}}子句将结果限制为您关心的每个数组中的两个对象,然后将每个{{1 }}并用两种不同的方法。