Как сделать левое внешнее соединение с массивом? - PullRequest
0 голосов
/ 10 февраля 2020

У меня проблемы с выполнением левого внешнего соединения с задействованным массивом jsonb.

Моя схема:

CREATE TABLE IF NOT EXISTS cusips (
  name TEXT,
  cusip TEXT,
  ticker TEXT
);

CREATE TABLE IF NOT EXISTS companies (
  name TEXT,
  data JSONB
);

Мой запрос:

INSERT INTO cusips (name, cusip, ticker) VALUES
  ('Berkshire Official', '90210', 'BRKA'),
  ('Apple Corp', '90211', 'AAPL'),
  ('Microsoft Company', '90212', 'MSFT');

INSERT INTO companies (name, data) VALUES
  ('Berkshire', '{"tickers": ["BRKA", "BRKB"]}'),
  ('Apple', '{"tickers": ["AAPL"]}'),
  ('Microsoft', '{"tickers": ["MSFT"]}');

SELECT * FROM (SELECT name, cusip, ticker FROM cusips) c,
  LATERAL (
   SELECT jsonb_array_elements(data->'tickers') AS ticker
   FROM companies
   WHERE ticker::TEXT = 'BRKA'
  ) cc
WHERE c.cusip = '90210'

Этот запрос возвращает:

name        cusip   ticker  ticker
Berkshire   90210   BRKA    "BRKA"
Berkshire   90210   BRKA    "BRKB"
Berkshire   90210   BRKA    "AAPL"
Berkshire   90210   BRKA    "MSFT"

Я хотел бы одну строку с название, cusip и все данные для компании (в данном случае это просто тикеры) ... например:

name        cusip   data
Berkshire   90210   {"tickers": ["BRKA", "BRKB"]}

РЕДАКТИРОВАТЬ: Хотя я мог присоединиться к названию компании, имена часто разные между таблицами, поэтому я должен присоединиться к тикеру.

http://sqlfiddle.com/#! 17 / fa376 / 2

Ответы [ 2 ]

2 голосов
/ 10 февраля 2020

Ответ Ника кажется самым разумным ответом. Если по какой-то причине вы хотите деконструировать JSON и реконструировать его, вы можете использовать:

SELECT c.name, c.cusip, c.ticker, 
       jsonb_build_object('tickers', jsonb_agg(cc.ticker))
FROM cusips c CROSS JOIN LATERAL
     (SELECT jsonb_array_elements(co.data->'tickers') AS ticker
      FROM companies co
      WHERE co.name = c.name
     ) cc
WHERE c.cusip = '90210'
GROUP BY c.name, c.cusip, c.ticker;

Здесь - соответствующая скрипта db <>.

2 голосов
/ 10 февраля 2020

Кажется, вы просто хотите JOIN между таблицами:

SELECT c.name, c.cusip, cc.data
FROM cusips c
JOIN companies cc ON cc.name= c.name
WHERE c.cusip = '90210'

Вывод:

name        cusip   data
Berkshire   90210   {"tickers": ["BRKA", "BRKB"]}

Демонстрация по SQLFiddle

Если вам нужно сопоставить тикеры, потому что столбцы name могут не совпадать по какой-то причине, вы можете использовать оператор @>, чтобы проверить, существует ли тикер в массиве tickers:

SELECT c.name, c.cusip, cc.data
FROM cusips c
JOIN companies cc ON cc.data->'tickers' @> to_jsonb(c.ticker)
WHERE c.cusip = '90210'

Вывод:

name        cusip   data
Berkshire   90210   {"tickers": ["BRKA", "BRKB"]}

Демонстрация по SQLFiddle

...