Que signifie [FROM x, y] dans Postgres?

12

Je commence juste avec Postgres. En lisant ce document, je suis tombé sur cette requête:

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;

Je peux tout comprendre dans cette requête, sauf pour cela: FROM apod, ....

Qu'est-ce ,que cela signifie? J'ai l'habitude des jointures mais pas de plusieurs FROMinstructions séparées par une virgule.

J'ai cherché sur le net en vain. Après l'avoir regardé et réfléchi, il me semble qu'il déclare une variable appelée requête afin de pouvoir l'utiliser plusieurs fois. Mais si c'est vrai, qu'est-ce que cela a à voir FROM?

andrerpena
la source

Réponses:

10

Il crée un implicite CROSS JOIN. C'est la syntaxe SQL-89.

Ici, j'utilise values(1)et values(2)pour créer des pseduo-tables (tables de valeurs) uniquement à titre d'exemples. La chose après eux t(x), et g(y)sont appelés FROM-Alias, le caractère à l'intérieur de la parenthèse est l'alias de la colonne ( xet yrespectivement). Vous pouvez tout aussi facilement créer un tableau pour tester cela.

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

Voici comment vous l'écririez maintenant.

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

De là, vous pouvez en faire un implicite INNER JOINen ajoutant un conditionnel.

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

Ou la INNER JOINsyntaxe explicite et plus récente ,

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

Donc, dans votre exemple ..

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

C'est essentiellement la même que la nouvelle syntaxe,

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

qui est en fait le même, dans ce cas, car to_tsquery()renvoie une ligne et non un ensemble comme,

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;

Cependant, ce qui précède pourrait potentiellement to_tsquery('neutrino|(dark & matter)')se produire deux fois, mais dans ce cas, il ne l'est pas - to_tsqueryest marqué comme STABLE (vérifié avec \dfS+ to_tsquery).

STABLEindique que la fonction ne peut pas modifier la base de données et qu'au sein d'une analyse de table unique, elle retournera systématiquement le même résultat pour les mêmes valeurs d'argument, mais que son résultat pourrait changer d'une instruction SQL à l'autre. Il s'agit de la sélection appropriée pour les fonctions dont les résultats dépendent des recherches dans la base de données, des variables de paramètres (comme le fuseau horaire actuel), etc. La famille de fonctions current_timestamp est considérée comme stable, car leurs valeurs ne changent pas dans une transaction.

Pour une comparaison plus complète des différences entre SQL-89 et SQL-92, voir également ma réponse ici

Evan Carroll
la source
Merci beaucoup. Je commence juste avec SQL. Il est logique que le ,soit une jointure croisée car il ne s'agit que d'un produit cartésien et aucune comparaison n'est impliquée. Pouvez-vous simplement répondre à 1 autre question S'IL VOUS PLAÎT? ce qui est t(x)en (values(1)) AS t(x)???
andrerpena
@andrerpena mis à jour.
Evan Carroll
1
tu es le meilleur. Explication limpide. Merci beaucoup.
andrerpena
Jamais entendu le terme "FROM alias" pour un alias de table . to_tsquery()renvoie une valeur et non une ligne . Et juste parce qu'une fonction est définie STABLE, cela ne signifie pas le planificateur de requêtes va éviter l' évaluation répétée. C'est possible .
Erwin Brandstetter
12

Le manuel contient des explications détaillées sur la virgule dans la FROMliste du chapitre Expressions de table :

La FROMclause dérive une table d'une ou plusieurs autres tables données dans une liste de référence de table séparée par des virgules.

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

Une référence de table peut être un nom de table (éventuellement qualifié de schéma) ou une table dérivée telle qu'une sous-requête, une JOINconstruction ou des combinaisons complexes de ceux-ci. Si plusieurs références de table sont répertoriées dans la FROMclause, les tables sont jointes (c'est-à-dire que le produit cartésien de leurs lignes est formé; voir ci-dessous).

Le fait que les références de table séparées par des virgules aient été définies dans une version antérieure du standard SQL que la JOINsyntaxe explicite ne rend pas la virgule incorrecte ou obsolète. Utilisez la syntaxe de jointure explicite, là où c'est techniquement nécessaire (voir ci-dessous) ou là où le texte de la requête est plus clair.

Le manuel à nouveau:

FROM T1 CROSS JOIN T2est équivalent à FROM T1 INNER JOIN T2 ON TRUE (voir ci-dessous). Il est également équivalent à FROM T1, T2.

Mais "équivalent" ne signifie pas identique . Il y a une différence subtile, comme le note le manuel :

Remarque
Cette dernière équivalence ne tient pas exactement lorsque plus de deux tables apparaissent, car JOINse lie plus étroitement que la virgule. Par exemple, ce FROM T1 CROSS JOIN T2 INNER JOIN T3 ON conditionn'est pas la même chose que FROM T1, T2 INNER JOIN T3 ON conditionparce que le conditionpeut référencer T1dans le premier cas mais pas dans le second.

Cette question connexe démontre la pertinence de la différence:

Fondamentalement, votre observation est exacte:

il me semble qu'il déclare une variable appelée requête afin de pouvoir l'utiliser plusieurs fois.

N'importe quelle fonction peut être utilisée comme "fonction de table" dans la FROMliste. Et les paramètres de fonction peuvent référencer des colonnes de toutes les tables à gauche de la fonction, car la notation:

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

est vraiment équivalent à:

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

Le manuel sur les requêtes LATÉRALES:

Les fonctions de tableau apparaissant dans FROMpeuvent également être précédées du mot clé LATERAL, mais pour les fonctions, le mot clé est facultatif ; dans tous les cas, les arguments de la fonction peuvent contenir des références aux colonnes fournies par les éléments FROM précédents.

Accentuation sur moi.

Le mot cléAS est un bruit complètement facultatif avant les alias de table (par opposition aux alias de colonne , où il est recommandé de ne pas les omettre ASpour éviter d'éventuelles ambiguïtés). Réponse connexe avec plus:

Erwin Brandstetter
la source