Configurar
CREATE TABLE persons
(
person_id int not null,
name TEXT
);
INSERT INTO persons VALUES
(1, 'Adam'),
(2, 'Paul'),
(3, 'Tye'),
(4, 'Sarah');
CREATE TABLE json_to_parse
(
person_id int not null,
block json
);
INSERT INTO json_to_parse VALUES
(1, '{"size": "small", "love": "x"}'),
(2, '{"size": "medium", "love": "xx"}'),
(3, '{"size": "big", "love": "xxx"}');
O erro
Isso funciona sem problemas
SELECT
*
FROM
json_to_parse
CROSS JOIN LATERAL
json_to_record(json_to_parse.block) AS my_json(size TEXT, love TEXT)
INNER JOIN
persons
ON
persons.person_id = json_to_parse.person_id;
mas isso não
SELECT
*
FROM
json_to_parse,
json_to_record(json_to_parse.block) AS my_json(size TEXT, love TEXT)
INNER JOIN
persons
ON
persons.person_id = json_to_parse.person_id;
e recebo o erro "referência inválida para a entrada da cláusula FROM para a tabela "json_to_parse""
Por que esse segundo erro de consulta? Os documentos deixam bem claro que LATERAL
é opcional para funções com valor de tabela
As funções de tabela que aparecem em
FROM
também podem ser precedidas pela palavra-chaveLATERAL
, mas para funções a palavra-chave é opcional; os argumentos da função podem conter referências a colunas fornecidas pelosFROM
itens precedentes em qualquer caso.
A palavra-chave
LATERAL
é sempre opcional para funções naFROM
lista. Esse não é o problema na sua consulta.Ligações explícitas
JOIN
mais fortes do que uma vírgula naFROM
lista. Esse é o problema. Veja:Sua segunda consulta está logicamente errada.
json_to_record(json_to_parse.block)
binds topersons
antes do resultado de both seria unido comjson_to_parse
, o que contradiz a referência inicial ajson_to_parse.block
. Daí o erro.Não há nada de errado com vírgulas na
FROM
lista em si . É apenas tipicamente mais fácil de ler e manter quando você coloca a condição de junção principal entre duas tabelas na cláusulaON
orUSING
de aJOIN
onde for viável. (E faz uma diferença funcional paraOUTER JOIN
!). Use a vírgula livremente quando for correto e apropriado.Enquanto damos opiniões, é assim que eu escreveria sua consulta:
Ou, se preferir soletrar:
TL;DR; Não misture comma-joins com explícitas joins. Na verdade, não use comma-joins de forma alguma.
Você tem uma vírgula-join na segunda consulta. Comma-joins são interpretadas como
CROSS JOIN
então você parece ter esperado que a consulta fosse interpretada da seguinte forma:o que realmente funciona, pois
LATERAL
é opcional.Mas como as junções por vírgula têm uma precedência menor do que a sintaxe de junção explícita, o que realmente acontece é isto:
* Eu sei que o Postgres não suporta essa sintaxe, mas outros SGBDs suportam, e você também pode usar uma subconsulta
Já que agora você tem um tipo de subconsulta,
LATERAL
não é opcional. Agora deve ser óbvio por que não funciona: os parênteses implícitos estão empurrando oINNER JOIN persons... ON...
para um escopo separado.Dos documentos :
Junções por vírgula são velharias. Junções explícitas foram introduzidas no SQL-92, e há muito poucos casos em que é mais legível usar junções por vírgula. Favoreça sempre a sintaxe de junção explícita .