PostgreSQL JSON - Подмножество вложенных списков

1

У меня есть столбец в базе данных PostgreSQL, который в основном представляет собой jsonified список кортежей python:

[
  ["Mobile","111-111-1111"],
  ["Office","222-222-2222"],
  ["Mobile","333-333-3333"],
  ["Fax","444-444-4444"],
]

Я хотел бы построить запрос, который возвращает подмножество списка, основанное на первом значении в каждом из вложенных списков. Ниже приведен psudo-запрос, который, надеюсь, проиллюстрирует, что мне нужно:

SELECT
  foo AS bar,
  (SELECT 
     element 
   FROM 
     phone_numbers 
   WHERE
     element::json->>0 = "Mobile") AS mobile_numbers
FROM
  db
;

mobile_numbers == [["Mobile","111-111-1111"],["Mobile","333-333-3333"]]

Я знаю только биты о json-операторах в PostgreSQL (и SQL-запросы вообще), в основном в словарях. Я могу найти много примеров здесь о том, как копать в вложенные словари и возвращать одно значение, но я не нашел ничего, что вполне соответствует тому, что мне нужно.

Спасибо за вашу помощь.

Теги:
list
jsonb

1 ответ

1
Лучший ответ

Предполагая, что столбец содержит допустимый json в качестве массива массивов, вы должны отключить внешний массив с помощью jsonb_array_elements(), фильтровать внутренние массивы (кортежи) с помощью первого (индекс 0) своих элементов и агрегировать результаты с помощью jsonb_agg().

with my_table(phone_numbers) as (
values
('[
  ["Mobile","111-111-1111"],
  ["Office","222-222-2222"],
  ["Mobile","333-333-3333"],
  ["Fax","444-444-4444"]
]'::jsonb)
)

select jsonb_agg(phone)
from my_table
cross join jsonb_array_elements(phone_numbers) as arr(phone)
where phone->>0 = 'Mobile'

                        jsonb_agg                         
----------------------------------------------------------
 [["Mobile", "111-111-1111"], ["Mobile", "333-333-3333"]]
(1 row) 
  • 0
    Прекрасно работает с небольшой настройкой! Я использовал оператор SELECT, который вы написали, как подзапрос в моем операторе SELECT, но вместо CROSS JOIN я использовал обычный JOIN, и оператор ON был ext_table._id = subq_table._id. Казалось, что CROSS JOIN дает все «мобильные» числа в таблице для каждой строки в моем внешнем запросе, тогда как обычное соединение дает «мобильные» числа только для этой строки. Возможно, не самый элегантный способ, но результат желаемый.
  • 0
    cross join <function> всегда боковое , вам не следует бояться декартового произведения, см., например, PostgreSQL json_array_elements в предложении FROM - почему это не декартово соединение?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню