Postgres запрос, вложенный в JSONB - PullRequest
0 голосов
/ 20 февраля 2020

У меня есть столбец JSONB, содержащий list из objects.>
Вот схема таблицы:

column Name | Datatype
---------------------
timestamp   | timestamp
  data      | JSONB 

Пример данных

1.

timestamp : 2020-02-02 19:01:21.571429+00
data : [
  {
    "tracker_id": "5",
    "position": 1
  },
  {
    "tracker_id": "11",
    "position": 2
  },
  {
    "tracker_id": "4",
    "position": 1
  }
]

2.

timestamp : 2020-02-02 19:01:23.571429+00
data : [
  {
    "tracker_id": "7",
    "position": 3
  },
  {
    "tracker_id": "4",
    "position": 2
  }
]

3.

timestamp : 2020-02-02 19:02:23.571429+00
data : [
  {
    "tracker_id": "5",
    "position": 2
  },
  {
    "tracker_id": "4",
    "position": 1
  }
]

Мне нужно найти количество переходов tracker_id от position: 1 до position: 2
Здесь вывод будет 2, поскольку tracker_id 4 и 5 изменили свои position с 1 на 2.

Примечание
Переход должен быть в порядке возрастания в зависимости от timestamp
Изменение position не должно быть в последовательных записях.
Я использую расширение timescaledb

До сих пор я пробовал запрашивать объекты в списке отдельных записей, но я не уверен, как объединить объекты списка каждой записи и запросите их.

Каким будет запрос для этого? Должен ли я записать хранимую процедуру вместо этого?

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Я не использую расширение timescaledb, поэтому я бы выбрал чистое SQL решение на основе unnesting json:

with t (timestamp,data) as (values
  (timestamp '2020-02-02 19:01:21.571429+00', '[
  {
    "tracker_id": "5",
    "position": 1
  },
  {
    "tracker_id": "11",
    "position": 2
  },
  {
    "tracker_id": "4",
    "position": 1
  }
]'::jsonb),
  (timestamp '2020-02-02 19:01:23.571429+00', '[
  {
    "tracker_id": "7",
    "position": 3
  },
  {
    "tracker_id": "4",
    "position": 2
  }
]
'::jsonb),
  (timestamp '2020-02-02 19:02:23.571429+00', '[
  {
    "tracker_id": "5",
    "position": 2
  },
  {
    "tracker_id": "4",
    "position": 1
  }
]
'::jsonb)
), unnested as (
  select t.timestamp, r.tracker_id, r.position
  from t
  cross join lateral jsonb_to_recordset(t.data) AS r(tracker_id text, position int)
)
select count(*)
from unnested u1
join unnested u2
  on u1.tracker_id = u2.tracker_id
 and u1.position = 1 
 and u2.position = 2
 and u1.timestamp < u2.timestamp;
1 голос
/ 20 февраля 2020

Существуют различные функции, которые помогут объединить несколько строк базы данных в одну структуру JSON: row_to_ json (), array_to_ json () и array_agg ().

затем используйте обычный оператор SELECT с предложением ORDER BY, чтобы получить нужные вам отметки времени / JSON, и используйте вышеуказанные функции для создания одного JSON struture.

...