2015-06-03 2 views
2

Мне интересно, можно ли сделать левое внешнее соединение между json_array_elements столбца таблицы и другой таблицы? Что-то вроде следующего, но это не работает.Postgresql left external join on json array

SELECT * 
FROM foo, 
    json_array_elements (foo.bars :: json) foo_bars 
LEFT OUTER JOIN bar ON (foo_bars ->> 'id') :: BIGINT = bar.ID; 

Структура таблицы как следующий

FOO 
------------------------------------------ 
| ID | NAME |   BARS   | 
|------------------------------------------| 
| 1 | FOO1 | [{ "id" : 1}, { "id" : 2 }]| 
|------------------------------------------| 
| 2 | FOO1 |    []    | 
------------------------------------------ 

BAR 
------------- 
| ID | NAME | 
|-------------| 
| 1 | BAR1 | 
|-------------| 
| 2 | BAR2 | 
------------- 

Я хотел бы ожидать выход запроса можно

-------------------------------------------------------- 
| ID | NAME |   BARS   | ID | NAME | 
|------------------------------------------|-------------| 
| 1 | FOO1 | [{ "id" : 1}, { "id" : 2 }]| 1 | BAR1 | 
|------------------------------------------|-------------| 
| 1 | FOO1 | [{ "id" : 1}, { "id" : 2 }]| 2 | BAR2 | 
|------------------------------------------|-------------| 
| 2 | FOO1 |    []    | null | null | 
-------------------------------------------------------- 
+0

"не работает." на самом деле не является хорошим описанием поведения запросов и желаемого поведения. –

ответ

7

Чтобы ответить на ваш вопрос: Да, это возможно, и ваш запрос делает именно это. Мы можем доказать это с помощью введения третьего ряда в foo таблицы: http://sqlfiddle.com/#!15/06dfe/2

Вашей проблема не с LEFT JOIN в json_array_elements, но с неявным боковыми перекрестным соединением. Ваш запрос эквивалентен:

SELECT * 
FROM foo 
    CROSS JOIN LATERAL json_array_elements (foo.bars :: json) foo_bars 
    LEFT OUTER JOIN bar ON (foo_bars ->> 'id') :: BIGINT = bar.ID; 

http://sqlfiddle.com/#!15/06dfe/5

То, что вы хотите это боковое левое соединение между foo и json_array_elements:

SELECT * 
FROM foo LEFT JOIN LATERAL 
    json_array_elements (foo.bars :: json) foo_bars ON true 
LEFT OUTER JOIN bar ON (foo_bars ->> 'id') :: BIGINT = bar.ID; 

http://sqlfiddle.com/#!15/06dfe/6

+1

Это отлично работает. Даже работает с null json. Раньше я никогда не слышал о SQL Fiddle. Хотелось бы, чтобы я мог дать вам 100 очков за это. – binarymelon