从 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

我真正需要的是:

  1. 查找特定类型的时间。 (找到数组中第一个符合条件的对象。)
  2. 将此数据 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;

关键是使用 JOINON 子句将结果限制为您关心的每个数组中的两个对象,然后将每个对象最多合并两行 Items.id 通过几种不同的方法合二为一。