¿Qué significa [DE x, y] en Postgres?

12

Recién estoy comenzando con Postgres. Al leer este documento me encontré con 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;

Puedo entender que todo en esta consulta, a excepción de lo siguiente: FROM apod, ....

¿Qué significa esto ,? Estoy acostumbrado a unir pero no a múltiples FROMdeclaraciones separadas por una coma.

Busqué en la red sin resultado. Después de mirarlo y pensar, me parece que está declarando una variable llamada consulta para que pueda usarla varias veces. Pero si esto es cierto, ¿con qué tiene que ver FROM?

andrerpena
fuente

Respuestas:

10

Crea un implícito CROSS JOIN. Es la sintaxis SQL-89.

Aquí uso values(1)y values(2)para crear pseduo-tables (tablas de valores) simplemente por ejemplos. Lo que está detrás de ellos t(x), y g(y)se llaman FROM-Alias, el carácter dentro del paréntesis es el alias de la columna ( xy yrespectivamente). Podría crear fácilmente una tabla para probar esto.

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

Así es como lo escribirías ahora.

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

Desde allí puede hacer que esto sea implícito INNER JOINagregando un condicional.

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

O la INNER JOINsintaxis explícita y más nueva ,

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

Entonces en tu ejemplo ...

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

Esto es esencialmente lo mismo que la sintaxis más nueva,

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

que en realidad es lo mismo, en este caso, porque to_tsquery()devuelve una fila y no un 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;

Sin embargo, lo anterior podría causar to_tsquery('neutrino|(dark & matter)')que ocurra dos veces, pero en este caso no lo hace - to_tsqueryestá marcado como ESTABLE (verificado con \dfS+ to_tsquery).

STABLEindica que la función no puede modificar la base de datos, y que dentro de un escaneo de una sola tabla devolverá de manera consistente el mismo resultado para los mismos valores de argumento, pero que su resultado podría cambiar en las declaraciones SQL. Esta es la selección adecuada para funciones cuyos resultados dependen de búsquedas en la base de datos, variables de parámetros (como la zona horaria actual), etc. (No es apropiado para los desencadenadores DESPUÉS que desean consultar filas modificadas por el comando actual). Tenga en cuenta también que La familia de funciones current_timestamp califica como estable, ya que sus valores no cambian dentro de una transacción.

Para una comparación más completa de las diferencias entre SQL-89 y SQL-92, vea también mi respuesta aquí

Evan Carroll
fuente
Muchas gracias. Estoy empezando con SQL. Tiene sentido ,que sea una unión cruzada, ya que es solo un producto cartesiano y no hay comparación involucrada. ¿Puedes responder 1 pregunta más POR FAVOR? que hay t(x)en (values(1)) AS t(x)???
andrerpena
@andrerpena actualizado.
Evan Carroll
1
Eress el mejor. Explicación cristalina. Gracias una tonelada.
andrerpena
Nunca escuché el término "DE alias" para un alias de tabla . to_tsquery()devuelve un valor no una fila . Y sólo porque se define una función STABLE, eso no significa que el planificador de consulta será evitar la evaluación repetida. Es posible .
Erwin Brandstetter
12

El manual tiene una explicación detallada de la coma en la FROMlista en el capítulo Expresiones de tabla :

La FROMCláusula deriva una tabla de una o más tablas dadas en una lista de referencia de tablas separadas por comas.

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

Una referencia de tabla puede ser un nombre de tabla (posiblemente calificado por el esquema) o una tabla derivada, como una subconsulta, una JOINconstrucción o combinaciones complejas de estos. Si se enumera más de una referencia de tabla en la FROMcláusula, las tablas se unen entre sí (es decir, se forma el producto cartesiano de sus filas; ver más abajo).

El hecho de que las referencias de tabla separadas por comas se hayan definido en una versión anterior del estándar SQL que la JOINsintaxis explícita no hace que la coma sea incorrecta u obsoleta. Utilice la sintaxis de unión explícita, donde sea técnicamente necesario (ver más abajo) o donde aclare el texto de la consulta.

El manual nuevamente:

FROM T1 CROSS JOIN T2es equivalente a FROM T1 INNER JOIN T2 ON TRUE (ver abajo). También es equivalente a FROM T1, T2.

Pero "equivalente" no significa idéntico . Hay una sutil diferencia, como señala el manual :

Tenga en cuenta
Esta última equivalencia no se cumple exactamente cuando aparecen más de dos tablas, porque se JOINune con más fuerza que la coma. Por ejemplo, FROM T1 CROSS JOIN T2 INNER JOIN T3 ON conditionno es lo mismo que FROM T1, T2 INNER JOIN T3 ON conditionporque conditionpuede hacer referencia T1en el primer caso pero no en el segundo.

Esta pregunta relacionada demuestra la relevancia de la diferencia:

Básicamente, su observación es exactamente correcta:

Me parece que está declarando una variable llamada consulta para que pueda usarla varias veces.

Cualquier función se puede usar como "función de tabla" en la FROMlista. Y los parámetros de la función pueden hacer referencia a columnas de todas las tablas a la izquierda de la función, porque la notación:

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

es realmente equivalente a:

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

El manual sobre consultas LATERALES:

Las funciones de tabla que aparecen FROMtambién pueden ir precedidas de la palabra clave LATERAL, pero para las funciones la palabra clave es opcional ; Los argumentos de la función pueden contener referencias a columnas proporcionadas por elementos FROM anteriores en cualquier caso.

El énfasis audaz es mío.

La palabra claveAS es ruido completamente opcional antes de los alias de tabla (a diferencia de los alias de columna , donde se recomienda no omitir ASpara evitar posibles ambigüedades). Respuesta relacionada con más:

Erwin Brandstetter
fuente