O que significa [FROM x, y] no Postgres?

12

Estou apenas começando com o Postgres. Lendo este documento, me deparei com esta consulta:

SELECT title, ts_rank_cd(textsearch, query) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE query @@ textsearch
ORDER BY rank DESC
LIMIT 10;

Eu posso entender tudo nessa consulta, exceto para isso: FROM apod, ....

O que isso ,significa? Estou acostumado a participar, mas não a várias FROMinstruções separadas por vírgula.

Eu procurei na net sem sucesso. Depois de analisar e pensar, parece-me que está declarando uma variável chamada query para que possa usá-la várias vezes. Mas se isso for verdade, o que isso tem a ver FROM?

andrerpena
fonte

Respostas:

10

Isso cria um implícito CROSS JOIN. É a sintaxe SQL-89.

Aqui eu uso values(1)e values(2)para criar pseduo-tables (tabelas de valores) apenas para exemplos. A coisa que está depois deles t(x), e g(y)é chamada de FROM-Aliases, o caractere entre parênteses é o alias da coluna ( xe yrespectivamente). Você poderia facilmente criar uma tabela para testar isso.

SELECT *
FROM (values(1)) AS t(x), (values(2)) AS g(y)

Aqui está como você escreveria agora.

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(2)) AS g(y);

A partir daí, você pode tornar isso implícito INNER JOINadicionando uma condicional.

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(1)) AS g(z)
WHERE x = z;

Ou a INNER JOINsintaxe explícita e mais recente ,

SELECT *
FROM (values(1)) AS t(x)
INNER JOIN (values(1)) AS g(z)
  ON ( x = z );

Então, no seu exemplo ..

FROM apod, to_tsquery('neutrino|(dark & matter)') query

É essencialmente o mesmo que a sintaxe mais recente,

FROM apod
CROSS JOIN to_tsquery('neutrino|(dark & matter)') AS query

que é realmente o mesmo, neste caso, porque to_tsquery()retorna uma linha e não um conjunto como,

SELECT title, ts_rank_cd(
  textsearch,
  to_tsquery('neutrino|(dark & matter)')
) AS rank
FROM apod
WHERE to_tsquery('neutrino|(dark & matter)') @@ textsearch
ORDER BY rank DESC
LIMIT 10;

No entanto, o acima pode potencialmente to_tsquery('neutrino|(dark & matter)')ocorrer duas vezes, mas neste caso não ocorre - to_tsqueryestá marcado como ESTÁVEL (verificado com \dfS+ to_tsquery).

STABLEindica que a função não pode modificar o banco de dados e que, em uma única varredura de tabela, retornará consistentemente o mesmo resultado para os mesmos valores de argumento, mas que seu resultado poderá mudar nas instruções SQL. Essa é a seleção apropriada para funções cujos resultados dependem de pesquisas no banco de dados, variáveis ​​de parâmetro (como o fuso horário atual), etc. (É inadequado para gatilhos AFTER que desejem consultar linhas modificadas pelo comando atual.) A família de funções current_timestamp é qualificada como estável, pois seus valores não mudam dentro de uma transação.

Para uma comparação mais completa das diferenças entre SQL-89 e SQL-92, veja também minha resposta aqui

Evan Carroll
fonte
Muito obrigado. Estou apenas começando com SQL. Faz sentido ,que seja uma junção cruzada, pois é apenas um produto cartesiano e não há comparação envolvida. Você pode responder mais uma pergunta POR FAVOR? o que é t(x)em (values(1)) AS t(x)???
andrerpena
@andrerpena updated.
Evan Carroll
1
você é o melhor. Explicação cristalina. Muito obrigado.
andrerpena
Nunca ouvi o termo "FROM alias" para um alias de tabela . to_tsquery()retorna um valor, não uma linha . E só porque uma função é definida STABLE, isso não significa que o planejador de comandos irá evitar a avaliação repetida. Ele pode .
Erwin Brandstetter 15/03
12

O manual possui explicações detalhadas para a vírgula na FROMlista do capítulo Expressões da tabela :

A FROMCláusula deriva uma tabela de uma ou mais outras tabelas fornecidas em uma lista de referência de tabela separada por vírgula.

FROM table_reference [, table_reference [, ...]]

Uma referência de tabela pode ser um nome de tabela (possivelmente qualificado pelo esquema) ou uma tabela derivada, como uma subconsulta, uma JOINconstrução ou combinações complexas delas. Se mais de uma referência de tabela estiver listada na FROMcláusula, as tabelas serão cruzadas (ou seja, o produto cartesiano de suas linhas será formado; veja abaixo).

O fato de que as referências de tabela separadas por vírgula foram definidas em uma versão anterior do padrão SQL que a JOINsintaxe explícita não torna a vírgula incorreta ou desatualizada. Use a sintaxe de junção explícita, onde for tecnicamente necessário (veja abaixo) ou onde torne o texto da consulta mais claro.

O manual novamente:

FROM T1 CROSS JOIN T2é equivalente a FROM T1 INNER JOIN T2 ON TRUE (veja abaixo). Também é equivalente a FROM T1, T2.

Mas "equivalente" não significa idêntico . Há uma diferença sutil, como observa o manual :

Nota
Essa última equivalência não se aplica exatamente quando mais de duas tabelas aparecem, porque JOINvincula mais fortemente que vírgula. Por exemplo, FROM T1 CROSS JOIN T2 INNER JOIN T3 ON conditionnão é o mesmo que FROM T1, T2 INNER JOIN T3 ON conditionporque a conditionreferência pode T1no primeiro caso, mas não no segundo.

Esta questão relacionada demonstra a relevância da diferença:

Basicamente, sua observação é exatamente correta:

parece-me que está declarando uma variável chamada query para que possa usá-la várias vezes.

Qualquer função pode ser usada como "função de tabela" na FROMlista. E os parâmetros da função podem fazer referência a colunas de todas as tabelas à esquerda da função, porque a notação:

FROM apod, to_tsquery('neutrino|(dark & matter)') query

é realmente equivalente a:

FROM apod CROSS JOIN LATERAL to_tsquery('neutrino|(dark & matter)') AS query

O manual sobre consultas LATERAIS:

As funções da tabela que aparecem FROMtambém podem ser precedidas pela palavra-chave LATERAL, mas para as funções a palavra-chave é opcional ; os argumentos da função podem conter referências a colunas fornecidas pelos itens FROM anteriores em qualquer caso.

Negrito ênfase minha.

A palavraAS - chave é um ruído completamente opcional antes dos aliases da tabela (em oposição aos aliases da coluna , onde é recomendável não omitir ASpara evitar possíveis ambiguidades). Resposta relacionada com mais:

Erwin Brandstetter
fonte