Syntaxe des requêtes

Les instructions de requête analysent une ou plusieurs tables ou expressions, et renvoient des lignes de calculs de résultats. Cette rubrique décrit la syntaxe des requêtes SQL dans Cloud Spanner SQL.

Syntaxe SQL

query_statement:
    [ table_hint_expr ][ join_hint_expr ]
query_expr query_expr: { select | ( query_expr ) | query_expr set_op query_expr } [ ORDER BY expression [{ ASC | DESC }] [, ...] ] [ LIMIT count [ OFFSET skip_rows ] ] select: SELECT [{ ALL | DISTINCT }] { [ expression. ]* | expression [ [ AS ] alias ] } [, ...] [ FROM from_item [ tablesample_type ] [, ...] ] [ WHERE bool_expression ] [ GROUP BY expression [, ...] ] [ HAVING bool_expression ] set_op: UNION { ALL | DISTINCT } | INTERSECT { ALL | DISTINCT } | EXCEPT { ALL | DISTINCT } from_item: { table_name [ table_hint_expr ] [ [ AS ] alias ] | join | ( query_expr ) [ table_hint_expr ] [ [ AS ] alias ] | field_path | { UNNEST( array_expression ) | UNNEST( array_path ) | array_path } [ table_hint_expr ] [ [ AS ] alias ] [ WITH OFFSET [ [ AS ] alias ] ] } table_hint_expr: '@{' table_hint_key = table_hint_value '}' table_hint_key: { FORCE_INDEX } join: from_item [ join_type ] [ join_method ] JOIN [ join_hint_expr ] from_item [ { ON bool_expression | USING ( join_column [, ...] ) } ] join_type: { INNER | CROSS | FULL [OUTER] | LEFT [OUTER] | RIGHT [OUTER] }

join_method:
{ HASH }
join_hint_expr: '@{' join_hint_key = join_hint_value [, ...] '}' join_hint_key: { FORCE_JOIN_ORDER | JOIN_TYPE } tablesample_type: TABLESAMPLE sample_method (sample_size percent_or_rows ) sample_method: { BERNOULLI | RESERVOIR } sample_size: numeric_value_expression percent_or_rows: { PERCENT | ROWS }




Notation :

  • Les crochets "[]" indiquent des clauses facultatives.
  • Les parenthèses "()" indiquent des parenthèses littérales.
  • La barre verticale "|" indique un opérateur logique "OR".
  • Les accolades "{}" renferment un ensemble d'options.
  • Une virgule suivie de points de suspension entre crochets "[, …]" indique que l'élément précédent peut être répété dans une liste séparée par des virgules.

Liste SELECT

Syntaxe :

SELECT  [{ ALL | DISTINCT }]
    { [ expression. ]* | expression [ [ AS ] alias ] } [, ...]

La liste SELECT définit les colonnes renvoyées par la requête. Les expressions de la liste SELECT peuvent faire référence à des colonnes de n'importe quel élément from_item de la clause FROM correspondante.

Chaque élément de la liste SELECT est l'un des éléments suivants :

  • *
  • expression
  • expression.*

SELECT *

SELECT *, souvent appelé sélecteur étoile, génère une colonne de sortie pour chaque colonne visible après l'exécution de la requête complète.

SELECT * FROM (SELECT "apple" AS fruit, "carrot" AS vegetable);

+-------+-----------+
| fruit | vegetable |
+-------+-----------+
| apple | carrot    |
+-------+-----------+

SELECT expression

Les éléments d'une liste SELECT peuvent être des expressions. Ces expressions ont une valeur unique et produisent une colonne de sortie, avec un alias explicite facultatif.

Si l'expression ne comporte pas d'alias explicite, elle reçoit un alias implicite conformément aux règles applicables aux alias implicites, le cas échéant. Sinon, la colonne est anonyme et vous ne pouvez pas y faire référence par son nom ailleurs dans la requête.

SELECT expression.*

Un élément d'une liste SELECT peut également prendre la forme expression.*. Dans ce cas-là, une colonne de sortie est générée pour chaque colonne ou champ d'expression de niveau supérieur. L'expression doit être soit un alias de table, soit une valeur unique de type de données contenant des champs, tel que STRUCT.

La requête suivante produit une colonne de sortie pour chaque colonne de la vue groceries intégrée à la table.

SELECT groceries.*
FROM (SELECT "milk" AS dairy,
             "eggs" AS protein,
             "bread" AS grain) AS groceries;

+-------+---------+-------+
| dairy | protein | grain |
+-------+---------+-------+
| milk  | eggs    | bread |
+-------+---------+-------+

Voici d'autres exemples :

SELECT l.location.*
FROM (SELECT STRUCT("Seattle" AS city, "Washington" AS state) AS location
      UNION ALL
      SELECT STRUCT("Phoenix" AS city, "Arizona" AS state) AS location) AS l;

+---------+------------+
| city    | state      |
+---------+------------+
| Seattle | Washington |
| Phoenix | Arizona    |
+---------+------------+
SELECT l.LOCATION[offset(0)].*
FROM (SELECT ARRAY<STRUCT<city STRING, state STRING>>[
                         ("Seattle", "Washington"),
                         ("Phoenix", "Arizona")] AS location) AS l;

+---------+------------+
| city    | state      |
+---------+------------+
| Seattle | Washington |
+---------+------------+

Modificateurs SELECT

Vous pouvez modifier les résultats renvoyés par une requête SELECT comme suit.

SELECT DISTINCT

Une instruction SELECT DISTINCT supprime les lignes en double et renvoie uniquement les lignes restantes. SELECT DISTINCT ne peut pas renvoyer les types de colonnes suivants :

  • STRUCT
  • ARRAY

SELECT ALL

Une instruction SELECT ALL renvoie toutes les lignes, y compris les lignes en double. SELECT ALL est le comportement par défaut de SELECT.

Utilisation de types STRUCT avec SELECT

  • Les requêtes qui renvoient un objet STRUCT à la racine du type renvoyé ne sont pas acceptées. Par exemple, la requête suivante n'est pas possible :

    SELECT STRUCT(1, 2) FROM Users;
    
  • Le renvoi d'un tableau de structures à la racine du type renvoyé est accepté. Par exemple, la requête suivante est possible :

    SELECT ARRAY(SELECT STRUCT(1, 2)) FROM Users;
    
  • Toutefois, les formes de requête pouvant renvoyer un objet STRUCT de valeur NULL dans un résultat de requête ne sont pas possibles. La requête suivante n'est donc pas acceptée :

    SELECT ARRAY(SELECT IF(TRUE, STRUCT(1, 2), NULL)) FROM Users;
    

Consultez également les remarques sur l'utilisation de STRUCTs dans les sous-requêtes.

Alias

Consultez la section Alias pour en savoir plus sur la syntaxe et la visibilité des alias de liste SELECT.

Clause FROM

La clause FROM indique la ou les tables à partir desquelles extraire des lignes, et comment associer ces lignes afin de générer un flux unique de lignes à traiter dans le reste de la requête.

Syntaxe

from_item: {
    table_name [ table_hint_expr ] [ [ AS ] alias ] |
    join |
    ( query_expr ) [ table_hint_expr ] [ [ AS ] alias ] |
    field_path |
    { UNNEST( array_expression ) | UNNEST( array_path ) | array_path }
        [ table_hint_expr ] [ [ AS ] alias ] [ WITH OFFSET [ [ AS ] alias ] ]
}
table_hint_expr: '@{' table_hint_key = table_hint_value '}' table_hint_key: { FORCE_INDEX }

table_name

Nom (éventuellement qualifié) d'une table existante.

SELECT * FROM Roster;
SELECT * FROM db.Roster;
Optimisations relatives aux tables

Les optimisations suivantes s'appliquent aux tables :

Clé d'optimisation Valeurs possibles Description
FORCE_INDEX Chaîne. Nom d'un index existant dans la base de données ou _BASE_TABLE pour utiliser la table de base plutôt qu'un index.
  • Si elle est définie sur le nom d'un index, utilisez cet index à la place de la table de base. Si l'index ne peut pas fournir toutes les colonnes nécessaires, effectuez une nouvelle jointure avec la table de base.
  • Si elle est définie sur la chaîne _BASE_TABLE, utilisez la table de base pour la stratégie d'index plutôt qu'un index. Notez qu'il s'agit de la seule valeur valide lorsque FORCE_INDEX est utilisé dans une expression d'optimisation d'instruction.

Remarque : FORCE_INDEX est en fait une directive et non une optimisation, ce qui signifie qu'une erreur est générée si l'index n'existe pas.

L'exemple suivant montre comment utiliser un index secondaire lors de la lecture d'une table, en ajoutant une directive d'index sous la forme @{FORCE_INDEX=index_name} au nom de la table :

SELECT s.SingerId, s.FirstName, s.LastName, s.SingerInfo
FROM Singers@{FORCE_INDEX=SingersByFirstLastName} AS s
WHERE s.FirstName = "Catalina" AND s.LastName > "M";

Vous pouvez inclure plusieurs index dans une requête, même si un seul index est accepté pour chaque référence de table distincte. Exemple :

SELECT s.SingerId, s.FirstName, s.LastName, s.SingerInfo, c.ConcertDate
FROM Singers@{FORCE_INDEX=SingersByFirstLastName} AS s JOIN
     Concerts@{FORCE_INDEX=ConcertsBySingerId} AS c ON s.SingerId = c.SingerId
WHERE s.FirstName = "Catalina" AND s.LastName > "M";

Pour en savoir plus sur les directives d'index, reportez-vous à la section Index secondaires.

jointure

Reportez-vous à la section Types de jointures ci-dessous.

select

( select ) [ [ AS ] alias ] est une sous-requête de table.

field_path

Dans la clause FROM, field_path est un chemin qui se résout en un champ dans un type de données. field_path peut conduire de manière arbitraire dans une structure de données imbriquée.

Parmi les exemples de valeurs field_path valides, on trouve :

SELECT * FROM T1 t1, t1.array_column;

SELECT * FROM T1 t1, t1.struct_column.array_field;

SELECT (SELECT ARRAY_AGG(c) FROM t1.array_column c) FROM T1 t1;

SELECT a.struct_field1 FROM T1 t1, t1.array_of_structs a;

SELECT (SELECT STRING_AGG(a.struct_field1) FROM t1.array_of_structs a) FROM T1 t1;

Les chemins d'accès de champ dans la clause FROM doivent se terminer par un champ de tableau. De plus, les chemins d'accès aux champs ne peuvent pas contenir de tableaux avant la fin du chemin d'accès. Par exemple, le chemin d'accès array_column.some_array.some_array_field n'est pas valide, car il contient un tableau avant la fin du chemin.

Remarque : Si un chemin ne comporte qu'un seul nom, il est interprété comme une table. Pour contourner ce problème, encapsulez le chemin à l'aide de UNNEST ou utilisez le chemin d'accès complet.

UNNEST

L'opérateur UNNEST prend un élément ARRAY et renvoie une table avec une ligne pour chaque élément de l'élément ARRAY. Vous pouvez également utiliser UNNEST en dehors de la clause FROM avec l'opérateur IN.

Pour les éléments ARRAY d'entrée de la plupart des types d'éléments, la sortie de UNNEST contient généralement une colonne. Cette colonne unique a un alias facultatif, que vous pouvez utiliser pour faire référence à la colonne ailleurs dans la requête. Les éléments ARRAYS contenant ces types d'éléments renvoient plusieurs colonnes :

  • STRUCT

UNNEST détruit l'ordre des éléments dans l'élément ARRAY d'entrée. Utilisez la clause WITH OFFSET facultative pour renvoyer une deuxième colonne avec les index des éléments de tableau (voir ci-dessous).

Pour un élément ARRAY de colonnes STRUCT d'entrée, UNNEST renvoie une ligne pour chaque colonne STRUCT, avec une colonne distincte pour chaque champ de colonne STRUCT. L'alias de chaque colonne est le nom du champ STRUCT correspondant.

Exemple

SELECT *
FROM UNNEST(ARRAY<STRUCT<x INT64, y STRING>>[(1, 'foo'), (3, 'bar')]);

+---+-----+
| x | y   |
+---+-----+
| 3 | bar |
| 1 | foo |
+---+-----+

La séparation de l'élément ARRAY peut être explicite ou implicite. En cas de séparation explicite, array_expression doit renvoyer une valeur ARRAY, mais n'a pas besoin de renvoyer un élément ARRAY et le mot clé UNNEST est requis.

Exemple :

SELECT * FROM UNNEST ([1, 2, 3]);

En cas de séparation implicite, array_path doit renvoyer un élément ARRAY et le mot clé UNNEST est facultatif.

Exemple :

SELECT x
FROM mytable AS t,
  t.struct_typed_column.array_typed_field1 AS x;

Dans ce scénario, array_path peut conduire de manière arbitraire dans une structure de données, mais le dernier champ doit être de type ARRAY. Aucun champ précédent de l'expression ne peut être de type ARRAY, car il n'est pas possible d'extraire un champ nommé d'un élément ARRAY.

UNNEST traite les objets NULL comme suit :

  • La valeur NULL et les objets ARRAY vides ne produisent aucune ligne.
  • Un élément ARRAY contenant des valeurs NULL génère des lignes contenant des valeurs NULL.

La clause facultative WITH OFFSET facultative renvoie une colonne distincte contenant la valeur "offset" (en comptant à partir de zéro) pour chaque ligne produite par l'opération UNNEST. Cette colonne contient un alias facultatif. L'alias par défaut est "offset".

Exemple :

SELECT * FROM UNNEST ( ) WITH OFFSET AS num;

Consultez la section Arrays topic pour connaître les autres façons d'utiliser l'opérateur UNNEST, y compris en cas de construction, de regroupement et de filtrage.

Sous-requêtes

Une sous-requête est une requête qui apparaît dans une autre instruction et qui s'écrit entre parenthèses. Elle est également appelée "sous-sélection" ou "sélection imbriquée". La syntaxe SELECT complète est valide dans les sous-requêtes.

Il existe deux types de sous-requêtes :

  • Les sous-requêtes d'expression, que vous pouvez utiliser dans une requête dès lors que des expressions sont valides. Les sous-requêtes d'expression renvoient une valeur unique.
  • Les sous-requêtes de table, que vous pouvez uniquement utiliser dans une clause FROM. La requête externe traite le résultat de la sous-requête en tant que table.

Notez que les deux types de sous-requêtes doivent être entre parenthèses.

Exemple :

SELECT AVG ( PointsScored )
FROM
( SELECT PointsScored
  FROM Stats
  WHERE SchoolID = 77 )

Une sous-requête de table peut éventuellement contenir un alias.

Exemple :

SELECT r.LastName
FROM
( SELECT * FROM Roster) AS r;

Notes sur les sous-requêtes

Lorsque vous utilisez des sous-requêtes :

  • Si une sous-requête d'expression renvoie plusieurs valeurs, les résultats de cette sous-requête doivent être renvoyés dans un tableau à l'aide du mot clé ARRAY. Si l'élément ARRAY n'est pas présent, la syntaxe de la sous-requête est légale, mais lorsque la requête est exécutée, cette sous-requête n'est pas autorisée à renvoyer plus d'une valeur par appel. Si plusieurs valeurs sont renvoyées, la requête échouera lors de l'exécution.
  • Les sous-requêtes d'expression qui sélectionnent plusieurs colonnes doivent renvoyer les valeurs de colonne dans une structure à l'aide de AS STRUCT.

Voici à quoi ce type de requête ressemble :

SELECT r.LastName, r.SchoolId,
       ARRAY(SELECT AS STRUCT p.OpponentID, p.PointsScored
             FROM PlayerStats AS p
             WHERE p.LastName = r.LastName) AS PlayerStats
FROM Roster AS r;

Faire appel à une sous-sélection pour extraire les lignes d'une table insérée est un modèle courant lors de la lecture de données issues de bases de données Cloud Spanner. Il est important de garder à l'esprit que la relation d'insertion ne fait pas partie du modèle de données SQL et que la sous-sélection doit alors joindre les lignes associées.

Voici un exemple de sous-requête qui sélectionne les lignes associées dans une table insérée et inclut une condition de jointure explicite :

SELECT ...
  ARRAY(
      SELECT AS STRUCT ...
      FROM ChildTable ct
      WHERE ct.parent_key = pt.parent_key
            -- The second part of the condition applies when the key is nullable
            OR (ct.parent_key IS NULL AND pt.parent_key IS NULL)) as child_rows
FROM ParentTable pt
WHERE ...;

Consultez également les remarques sur l'utilisation d'éléments STRUCT dans les listes SELECT.

Opérateur TABLESAMPLE

Vous pouvez utiliser l'opérateur TABLESAMPLE pour sélectionner un échantillon aléatoire d'un ensemble de données. Cet opérateur est utile lorsque vous travaillez avec des tables contenant de grandes quantités de données et que vous ne cherchez pas à obtenir des réponses précises.

Syntaxe :

tablesample_type:
    TABLESAMPLE sample_method (sample_size percent_or_rows )
sample_method: { BERNOULLI | RESERVOIR }
sample_size: numeric_value_expression
percent_or_rows: { PERCENT | ROWS }


Lorsque vous utilisez l'opérateur TABLESAMPLE, vous devez spécifier l'algorithme d'échantillonnage à utiliser :

  • BERNOULLI : chaque ligne est sélectionnée indépendamment avec la probabilité indiquée dans la clause percent. Par conséquent, vous obtenez environ N * percent/100 lignes.

  • RESERVOIR ; prend comme paramètre une taille d'échantillonnage réelle K (exprimée en nombre de lignes). Si l'entrée est inférieure à K, la relation d'entrée entière est générée. Si l'entrée est supérieure à K, l'échantillonnage "réservoir" produit un échantillon de taille exactement égale à K, où tout échantillon de taille K a une probabilité égale.

L'opérateur TABLESAMPLE exige que vous sélectionniez ROWS ou PERCENT. Si vous sélectionnez PERCENT, la valeur doit être comprise entre 0 et 100. Si vous sélectionnez ROWS, la valeur doit être supérieure ou égale à 0.

Les exemples suivants illustrent l'utilisation de l'opérateur TABLESAMPLE.

Sélectionnez le contenu d'une table en utilisant la méthode d'échantillonnage RESERVOIR :

SELECT MessageId
FROM Messages TABLESAMPLE RESERVOIR (100 ROWS);

Sélectionnez le contenu d'une table en utilisant la méthode d'échantillonnage BERNOULLI :

SELECT MessageId
FROM Messages TABLESAMPLE BERNOULLI (0.1 PERCENT);

Utilisation de TABLESAMPLE avec une sous-requête :

SELECT Subject FROM
(SELECT MessageId, Subject FROM Messages WHERE ServerId="test")
TABLESAMPLE BERNOULLI(50 PERCENT)
WHERE MessageId > 3;

Utilisation d'une opération TABLESAMPLE avec une jointure à une autre table.

SELECT S.Subject
FROM
(SELECT MessageId, ThreadId FROM Messages WHERE ServerId="test") AS R
TABLESAMPLE RESERVOIR(5 ROWS),
Threads AS S
WHERE S.ServerId="test" AND R.ThreadId = S.ThreadId;

Alias

Consultez la section Alias pour en savoir plus sur la syntaxe et la visibilité des alias des clauses FROM.

Types de jointures

Syntaxe

join:
    from_item [ join_type ] [ join_method ] JOIN  [ join_hint_expr ] from_item
    [ ON bool_expression | USING ( join_column [, ...] ) ]

join_type:
    { INNER | CROSS | FULL [OUTER] | LEFT [OUTER] | RIGHT [OUTER] }

join_method:
{ HASH }
join_hint_expr: '@{' join_hint_key = join_hint_value [, ...] '}' join_hint_key: { FORCE_JOIN_ORDER | JOIN_TYPE }



La clause JOIN fusionne deux éléments from_item afin que la clause SELECT puisse les interroger en tant que source unique. Les clauses join_type et ON ou USING (une "condition de jointure") spécifient comment combiner et supprimer les lignes de deux éléments from_item pour former une source unique.

Toutes les clauses JOIN nécessitent un élément join_type.

Une clause JOIN nécessite une condition de jointure, sauf si l'une des conditions suivantes est remplie :

  • La clause join_type est CROSS.
  • Un élément from_item, ou les deux, n'est pas une table, par exemple array_path ou field_path.

Optimisations de jointure

Les optimisations suivantes sont compatibles avec JOIN :

Clé d'optimisation Valeurs possibles Description
FORCE_JOIN_ORDER TRUE
FALSE (valeur par défaut)
Si elle est définie sur "true", utilisez l'ordre de jointure spécifié dans la requête.
JOIN_TYPE HASH_JOIN
APPLY_JOIN
LOOP_JOIN

Lorsque vous mettez en œuvre une jointure logique, choisissez une alternative spécifique à utiliser pour la méthode de jointure sous-jacente. Pour en savoir plus, consultez la rubrique Méthodes de jointure.
Pour utiliser une jointure HASH, utilisez HASH JOIN ou JOIN@{JOIN_TYPE=HASH_JOIN}, mais pas les deux.

Méthodes de jointure

Les méthodes de jointure sont des mises en œuvre spécifiques des différents types de jointure logique. Certaines méthodes de jointure ne sont disponibles que pour certains types de jointure. Le choix de la méthode de jointure à utiliser dépend des spécificités de votre requête et des données interrogées. Le meilleur moyen de déterminer si une méthode de jointure donnée contribue à améliorer les performances de votre requête est de l'essayer et d'afficher le plan d'exécution de la requête obtenu. Pour en savoir plus, consultez Opérateurs d'exécution de requête, en particulier les sections relatives aux opérateurs d'application, de jointure par hachage et de jointure par boucle.

Méthode de jointure Description Opérandes
HASH_JOIN L'opérateur de jointure par hachage crée une table de hachage à partir d'un côté (le côté construction) et y sonde tous les éléments contenus de l'autre côté (le côté vérification). Différentes variantes sont utilisées pour différents types de jointure. Affichez le plan d'exécution de la requête pour voir quelle variante est utilisée. Obtenez plus d'informations sur l'opérateur de jointure par hachage.
APPLY_JOIN L'opérateur de jointure par application extrait chaque élément d'un côté (le côté entrée) et évalue la sous-requête de l'autre côté (le côté mise en correspondance) en utilisant les valeurs de l'élément du côté entrée. Différentes variantes sont utilisées pour différents types de jointure. L'application croisée est utilisée pour la jointure interne et l'application externe pour les jointures gauches. Obtenez plus d'informations sur les opérateurs cross apply et outer apply.
LOOP_JOIN L'opérateur de jointure par boucle parcourt chaque élément d'un côté et y recherche chaque élément de l'autre côté. Différentes variantes sont utilisées pour différents types de jointure. Affichez le plan d'exécution de la requête pour voir quelle variante est utilisée. Obtenez plus d'informations sur l'opérateur de jointure par boucle.

JOINTURE [INTERNE]

Une jointure INNER JOIN, ou simplement JOIN, calcule efficacement le produit cartésien des deux éléments from_item et supprime toutes les lignes qui ne répondent pas à la condition de jointure. "Efficacement" signifie qu'il est possible de mettre en œuvre une jointure INNER JOIN sans calculer réellement le produit cartésien.

JOINTURE CROISÉE

Une jointure CROSS JOIN renvoie le produit cartésien des deux éléments from_item. En d'autres termes, elle conserve toutes les lignes des deux éléments from_item et combine chaque ligne du premier élément from_item avec chaque ligne du deuxième élément from_item.

Jointures croisées séparées par des virgules

Les jointures CROSS JOIN peuvent être écrites explicitement (voir ci-dessus) ou implicitement en utilisant des éléments from_item séparés par des virgules.

Exemple de "jointure implicite séparée par une virgule" :

SELECT * FROM Roster, TeamMascot;

Voici l'équivalent explicite des jointures croisées :

SELECT * FROM Roster CROSS JOIN TeamMascot;

Vous ne pouvez pas écrire de jointures croisées séparées par des virgules entre parenthèses.

Non valide. Jointure séparée par une virgule entre parenthèses :

SELECT * FROM t CROSS JOIN (Roster, TeamMascot);  // INVALID.

Consultez la rubrique Séquences de clauses JOIN pour en savoir plus sur le comportement d'une jointure croisée séparée par une virgule dans une séquence de clauses JOIN.

JOINTURE [EXTERNE] COMPLÈTE

Une jointure FULL OUTER JOIN (ou simplement FULL JOIN) renvoie tous les champs pour toutes les lignes dans les deux éléments from_item répondant à la condition de jointure.

FULL indique que toutes les lignes des deux éléments from_item sont renvoyées, même si elles ne répondent pas à la condition de jointure.

OUTER indique que si une ligne donnée d'un élément from_item ne rejoint aucune ligne de l'autre from_item, la ligne sera renvoyée avec des valeurs NULL pour toutes les colonnes de l'autre from_item.

JOINTURE [EXTERNE] GAUCHE

Le résultat d'une jointure LEFT OUTER JOIN (ou simplement de LEFT JOIN) pour deux éléments from_item conserve toujours toutes les lignes de l'élément from_item gauche dans la clause JOIN, même si aucune ligne dans l'élément from_item droit ne satisfait le prédicat de jointure.

LEFT indique que toutes les lignes de l'élément from_item gauche sont renvoyées. Si une ligne donnée de l'élément from_item gauche ne rejoint aucune ligne de l'élément from_item droit, la ligne sera renvoyée avec des valeurs NULL pour toutes les colonnes de l'élément from_item droit. Les lignes de l'élément from_item droit qui ne rejoignent aucune ligne de l'élément from_item gauche sont supprimées.

JOINTURE [EXTERNE] DROITE

Le résultat d'une jointure RIGHT OUTER JOIN (ou simplement de RIGHT JOIN) est semblable et symétrique à celui d'une jointure LEFT OUTER JOIN.

Clause ON

La clause ON contient une expression bool_expression. Une ligne combinée (le résultat de la jointure de deux lignes) répond à la condition de jointure si bool_expression renvoie l'attribut TRUE.

Exemple :

SELECT * FROM Roster INNER JOIN PlayerStats
ON Roster.LastName = PlayerStats.LastName;

Clause USING

La clause USING requiert une liste column_list contenant une ou plusieurs colonnes qui apparaissent dans les deux tables d'entrée. Il effectue une comparaison d'égalité sur cette colonne et les lignes remplissant la condition de jointure si la comparaison d'égalité renvoie TRUE.

Dans la plupart des cas, une instruction contenant le mot clé USING équivaut à utiliser le mot clé ON. Par exemple, l'instruction :

SELECT FirstName
FROM Roster INNER JOIN PlayerStats
USING (LastName);

équivaut à :

SELECT FirstName
FROM Roster INNER JOIN PlayerStats
ON Roster.LastName = PlayerStats.LastName;

Les résultats des requêtes contenant USING diffèrent des requêtes qui utilisent ON lorsque vous incluez SELECT *. Pour illustrer cela, prenons pour exemple la requête suivante :

SELECT * FROM Roster INNER JOIN PlayerStats
USING (LastName);

Cette instruction renvoie les lignes de Roster et PlayerStats, où Roster.LastName est identique à PlayerStats.LastName. Les résultats incluent une seule colonne LastName.

Envisagez maintenant la requête suivante :

SELECT * FROM Roster INNER JOIN PlayerStats
ON Roster.LastName = PlayerStats.LastName;

Cette instruction renvoie les lignes de Roster et PlayerStats, où Roster.LastName est identique à PlayerStats.LastName. Les résultats incluent deux colonnes LastName : une issue de Roster et l'autre de PlayerStats.

Séquences de clauses JOIN

La clause FROM peut contenir plusieurs clauses JOIN en séquence.

Exemple :

SELECT * FROM a LEFT JOIN b ON TRUE LEFT JOIN c ON TRUE;

a, b et c sont des éléments from_item. Les clauses JOIN sont liées de gauche à droite, mais vous pouvez insérer des parenthèses pour les regrouper dans un ordre différent.

Considérez les requêtes suivantes : A (sans parenthèses) et B (avec parenthèses) sont équivalentes, mais ne ressemblent pas à C. La jointure FULL JOIN en gras est la première à être appliquée.

A.

SELECT * FROM Roster FULL JOIN TeamMascot USING (SchoolID)
FULL JOIN PlayerStats USING (LastName);

B.

SELECT * FROM ( (Roster FULL JOIN TeamMascot USING (SchoolID))
FULL JOIN PlayerStats USING (LastName));

C.

SELECT * FROM (Roster FULL JOIN (TeamMascot FULL JOIN PlayerStats USING
(LastName)) USING (SchoolID)) ;

Lorsque des jointures croisées sont présentes dans une requête avec une séquence de clauses JOIN, elles se groupent de gauche à droite comme les autres types JOIN.

Exemple :

SELECT * FROM a JOIN b ON TRUE, b JOIN c ON TRUE;

La requête ci-dessus est équivalente à

SELECT * FROM ((a JOIN b ON TRUE) CROSS JOIN b) JOIN c ON TRUE);

Il ne peut y avoir de jointure RIGHT JOIN, ni FULL JOIN après une jointure séparée par des virgules.

Non valide. RIGHT JOIN après une jointure croisée séparée par des virgules :

SELECT * FROM Roster, TeamMascot RIGHT JOIN PlayerStats ON TRUE;  // INVALID.

Clause WHERE

Syntaxe

WHERE bool_expression

La clause WHERE filtre les lignes en évaluant chaque ligne par rapport à l'expression bool_expression et supprime toutes les lignes qui ne renvoient pas TRUE (c'est-à-dire, toutes les lignes renvoyant FALSE ou NULL).

Exemple :

SELECT * FROM Roster
WHERE SchoolID = 52;

L'expression bool_expression peut contenir plusieurs sous-conditions.

Exemple :

SELECT * FROM Roster
WHERE STARTS_WITH(LastName, "Mc") OR STARTS_WITH(LastName, "Mac");

Vous ne pouvez pas faire référence à des alias de colonne dans la liste SELECT de la clause WHERE.

Les expressions des jointures INNER JOIN ont une expression équivalente dans la clause WHERE. Par exemple, une requête utilisant une jointure INNER JOIN et ON possède une expression équivalente à l'aide d'une jointure CROSS JOIN et WHERE.

Par exemple, la requête suivante :

SELECT * FROM Roster INNER JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

équivaut à :

SELECT * FROM Roster CROSS JOIN TeamMascot
WHERE Roster.SchoolID = TeamMascot.SchoolID;

Clause GROUP BY

Syntaxe

GROUP BY expression [, ...]

La clause GROUP BY regroupe les lignes d'une table avec des valeurs non distinctes pour l'expression dans la clause GROUP BY. Si plusieurs lignes sont présentes dans la table source contenant des valeurs non distinctes pour expression, la clause GROUP BY génère une seule ligne combinée. GROUP BY est couramment utilisé lorsque des fonctions d'agrégat sont présentes dans la liste SELECT ou pour éliminer les redondances dans le résultat. Le type de données de l'expression doit être groupable.

Exemple :

SELECT SUM(PointsScored), LastName
FROM PlayerStats
GROUP BY LastName;

La clause GROUP BY peut faire référence à des noms d'expression dans la liste SELECT. La clause GROUP BY autorise également les références ordinales aux expressions de la liste SELECT à l'aide de valeurs entières. 1 fait référence à la première expression de la liste SELECT, 2 à la deuxième, etc. La liste d'expressions peut combiner des ordinaux et des noms d'expressions.

Exemple :

SELECT SUM(PointsScored), LastName, FirstName
FROM PlayerStats
GROUP BY LastName, FirstName;

La requête ci-dessus est équivalente à :

SELECT SUM(PointsScored), LastName, FirstName
FROM PlayerStats
GROUP BY 2, FirstName;

Les clauses GROUP BY peuvent également faire référence à des alias. Si une requête contient des alias dans la clause SELECT, ceux-ci remplacent les noms dans la clause FROM correspondante.

Exemple :

SELECT SUM(PointsScored), LastName as last_name
FROM PlayerStats
GROUP BY last_name;

Clause HAVING

Syntaxe

HAVING bool_expression

La clause HAVING est semblable à la clause WHERE : elle filtre et exclut les lignes qui ne renvoient pas TRUE lorsqu'elles sont évaluées à l'aide de bool_expression.

À l'instar de la clause WHERE, l'expression bool_expression peut être toute expression renvoyant une valeur booléenne et peut contenir plusieurs sous-conditions.

Les clauses HAVING et WHERE ont les différences suivantes :

  • La clause HAVING requiert que GROUP BY ou qu'une agrégation soit présent dans la requête.
  • La clause HAVING apparaît après GROUP BY et l'agrégation, et avant ORDER BY. Cela signifie que la clause HAVING est évaluée une fois pour chaque ligne agrégée de l'ensemble de résultats. Ce point est différent pour la clause WHERE, qui est évaluée avant GROUP BY et l'agrégation.

La clause HAVING peut référencer des colonnes disponibles via la clause FROM, ainsi que des alias de la liste SELECT. Les expressions référencées dans la clause HAVING doivent figurer dans la clause GROUP BY ou être le résultat d'une fonction d'agrégation :

SELECT LastName
FROM Roster
GROUP BY LastName
HAVING SUM(PointsScored) > 15;

Si une requête contient des alias dans la clause SELECT, ceux-ci remplacent les noms dans une clause FROM.

SELECT LastName, SUM(PointsScored) AS ps
FROM Roster
GROUP BY LastName
HAVING ps > 0;

Agrégation obligatoire

L'agrégation ne doit pas nécessairement être présente dans la clause HAVING elle-même, mais doit être présente sous au moins l'une des formes suivantes :

Fonction d'agrégation dans la liste SELECT

SELECT LastName, SUM(PointsScored) AS total
FROM PlayerStats
GROUP BY LastName
HAVING total > 15;

Fonction d'agrégation dans la clause HAVING

SELECT LastName
FROM PlayerStats
GROUP BY LastName
HAVING SUM(PointsScored) > 15;

Agrégation dans la liste SELECT et la clause HAVING

Lorsque des fonctions d'agrégation sont présentes à la fois dans la liste SELECT et dans la clause HAVING, les fonctions d'agrégation et les colonnes auxquelles elles font référence n'ont pas besoin d'être identiques. Dans l'exemple ci-dessous, les deux fonctions d'agrégation, COUNT() et SUM(), sont différentes et utilisent également des colonnes différentes.

SELECT LastName, COUNT(*)
FROM PlayerStats
GROUP BY LastName
HAVING SUM(PointsScored) > 15;

Clause ORDER BY

Syntaxe

ORDER BY expression [{ ASC | DESC }] [, ...]

La clause ORDER BY spécifie une colonne ou une expression en tant que critère de tri pour l'ensemble de résultats. Si aucune clause ORDER BY n'est présente, l'ordre des résultats d'une requête n'est pas défini. Le sens de tri par défaut est ASC. Les résultats sont triés dans l'ordre croissant des valeurs d'expression. DESC trie les résultats par ordre décroissant. Les alias de colonnes d'une clause FROM ou d'une liste SELECT sont autorisés. Si une requête contient des alias dans la clause SELECT, ceux-ci remplacent les noms dans la clause FROM correspondante.

Il est possible de trier à partir de plusieurs colonnes. Dans l'exemple ci-dessous, l'ensemble de résultats est d'abord trié par SchoolID, puis par LastName :

SELECT LastName, PointsScored, OpponentID
FROM PlayerStats
ORDER BY SchoolID, LastName;

Les règles suivantes s'appliquent lors du tri des valeurs :

  • NULL : dans le contexte de la clause ORDER BY, les valeurs NULL sont la plus petite valeur possible, c'est-à-dire que les valeurs NULL apparaissent en premier dans les tris ASC et en dernier dans les tris DESC.
  • Types de données avec virgule flottante : consultez la section Sémantique de la virgule flottante pour le tri et le regroupement.

Lorsqu'elle est utilisée conjointement avec des opérateurs d'ensemble, la clause ORDER BY s'applique à l'ensemble de résultats de la requête entière. Elle ne s'applique pas uniquement à l'instruction SELECT la plus proche. Pour cette raison, il peut être utile (mais ce n'est pas obligatoire) d'utiliser des parenthèses pour indiquer la portée de la clause ORDER BY.

Cette requête sans parenthèses :

SELECT * FROM Roster
UNION ALL
SELECT * FROM TeamMascot
ORDER BY SchoolID;

est équivalente à la requête suivante avec des parenthèses :

( SELECT * FROM Roster
  UNION ALL
  SELECT * FROM TeamMascot )
ORDER BY SchoolID;

mais n'est pas équivalente à la requête ci-dessous, où la clause ORDER BY s'applique uniquement à la deuxième instruction SELECT :

SELECT * FROM Roster
UNION ALL
( SELECT * FROM TeamMascot
  ORDER BY SchoolID );

Vous pouvez également utiliser des valeurs littérales entières comme références de colonne dans les clauses ORDER BY. Une valeur littérale entière devient un ordinal (par exemple, le comptage commence à 1) dans la liste SELECT.

Par exemple, les deux requêtes suivantes sont équivalentes :

SELECT SUM(PointsScored), LastName
FROM PlayerStats
ORDER BY LastName;
SELECT SUM(PointsScored), LastName
FROM PlayerStats
ORDER BY 2;

COLLATE

Vous pouvez utiliser la clause COLLATE pour affiner le mode de tri des données spécifié par une clause ORDER BY. Le terme classement fait référence à un ensemble de règles qui déterminent la manière dont les valeurs de type STRING sont comparées en fonction des conventions et des normes d'une langue, d'une région ou d'un pays particulier. Ces règles peuvent définir la séquence de caractères correcte, avec des options permettant de spécifier l'insensibilité à la casse.

Remarque : Vous ne pouvez utiliser COLLATE que sur des colonnes de type STRING.

Ajoutez un classement à votre instruction comme suit :

SELECT ...
FROM ...
ORDER BY value COLLATE collation_string

Un élément collation_string contient un nom collation_name et peut avoir un attribut collation_attribute facultatif comme suffixe, séparé par un signe deux-points. L'élément collation_string est un littéral ou un paramètre. Généralement, ce nom est composé de deux lettres représentant la langue, suivies éventuellement d'un trait de soulignement et de deux lettres représentant la région, par exemple en_US. Ces noms sont définis par le projet CLDR (Common Locale Data Repository). Une instruction peut également avoir un nom collation_name ayant la valeur unicode. Celle-ci signifie que l'instruction doit renvoyer des données à l'aide du classement Unicode par défaut.

En plus du nom collation_name, un élément collation_string peut avoir un attribut collation_attribute facultatif comme suffixe, séparé par un signe deux-points. Cet attribut spécifie si les comparaisons de données doivent être sensibles à la casse. Les valeurs autorisées sont cs (sensibles à la casse) et ci (insensibles à la casse). Si aucun attribut collation_attribute n'est fourni, les valeurs par défaut du projet CLDR sont utilisées.

Exemples de clause COLLATE

Classer les résultats à l'aide du code de langue Anglais–Canada :

SELECT Place
FROM Locations
ORDER BY Place COLLATE "en_CA"

Classer les résultats à l'aide d'un paramètre :

#@collate_param = "arg_EG"
SELECT Place
FROM Locations
ORDER BY Place COLLATE @collate_param

Utiliser plusieurs clauses COLLATE dans une instruction :

SELECT APlace, BPlace, CPlace
FROM Locations
ORDER BY APlace COLLATE "en_US" ASC,
         BPlace COLLATE "ar_EG" DESC,
         CPlace COLLATE "en" DESC

Classement insensible à la casse :

SELECT Place
FROM Locations
ORDER BY Place COLLATE "en_US:ci"

Classement insensible à la casse Unicode par défaut :

SELECT Place
FROM Locations
ORDER BY Place COLLATE "unicode:ci"

Opérateurs d'ensemble

Syntaxe

UNION { ALL | DISTINCT } | INTERSECT { ALL | DISTINCT } | EXCEPT { ALL | DISTINCT }

Les opérateurs d'ensemble combinent les résultats de deux requêtes d'entrée ou plus dans un seul ensemble de résultats. Vous devez spécifier ALL ou DISTINCT. Si vous spécifiez ALL, toutes les lignes sont conservées. Si DISTINCT est spécifié, les lignes en double sont supprimées.

Si une ligne R donnée apparaît exactement m fois dans la première requête d'entrée et n fois dans la deuxième requête d'entrée (m >= 0, n >= 0) :

  • Pour UNION ALL, R apparaît exactement m + n fois dans le résultat.
  • Pour INTERSECT ALL, R apparaît exactement "MIN(m, n)" fois dans le résultat.
  • Pour EXCEPT ALL, R apparaît exactement "MAX(m - n, 0)" fois dans le résultat.
  • Pour UNION DISTINCT, la valeur DISTINCT est calculée après le calcul de UNION. R apparaît donc exactement une fois.
  • Pour INTERSECT DISTINCT, la valeur de DISTINCT est calculée après le calcul du résultat ci-dessus.
  • Pour EXCEPT DISTINCT, la ligne R apparaît une fois dans la sortie si m > 0 et n = 0.
  • S'il y a plus de deux requêtes d'entrée, les opérations ci-dessus se généralisent et le résultat est le même que si les entrées étaient combinées de manière incrémentielle de la gauche vers la droite.

Les règles suivantes s'appliquent :

  • Pour définir des opérations autres que UNION ALL, tous les types de colonne doivent permettre la comparaison d'égalité.
  • Les requêtes d'entrée de chaque côté de l'opérateur doivent renvoyer le même nombre de colonnes.
  • Les opérateurs associent les colonnes renvoyées par chaque requête d'entrée en fonction des positions des colonnes dans leurs listes SELECT respectives. Autrement dit, la première colonne de la première requête d'entrée est associée à la première colonne de la deuxième requête d'entrée.
  • L'ensemble de résultats utilise toujours les noms de colonne de la première requête d'entrée.
  • L'ensemble de résultats utilise toujours les supertypes des types d'entrée dans les colonnes correspondantes. Par conséquent, les colonnes associées doivent également avoir le même type de données ou un supertype commun.
  • Vous devez utiliser des parenthèses pour séparer les différentes opérations d'ensemble. Ainsi, à cette fin, les opérations d'ensemble UNION ALL et UNION DISTINCT sont différentes. Si l'instruction ne répète que la même opération d'ensemble, les parenthèses ne sont pas nécessaires.

Exemples :

query1 UNION ALL (query2 UNION DISTINCT query3)
query1 UNION ALL query2 UNION ALL query3

Incorrect :

query1 UNION ALL query2 UNION DISTINCT query3
query1 UNION ALL query2 INTERSECT ALL query3; // INVALID.

UNION

L'opérateur UNION associe les ensembles de résultats de deux requêtes d'entrée ou plus en associant des colonnes de l'ensemble de résultats de chaque requête et en les concaténant verticalement.

INTERSECT

L'opérateur INTERSECT renvoie les lignes trouvées dans les ensembles de résultats des requêtes d'entrée de gauche et de droite. Contrairement à EXCEPT, le positionnement des requêtes d'entrée (à gauche et à droite de l'opérateur INTERSECT) n'a pas d'importance.

EXCEPT

L'opérateur EXCEPT renvoie les lignes de la requête d'entrée de gauche qui ne figurent pas dans la requête d'entrée de droite.

Clause LIMIT et clause OFFSET

Syntaxe

LIMIT count [ OFFSET skip_rows ]

LIMIT spécifie une valeur count non négative de type INT64, et pas plus de count lignes seront renvoyées. LIMIT 0 renvoie 0 ligne. En cas d'opération d'ensemble, LIMIT est appliqué après l'évaluation de l'opération d'ensemble.

OFFSET spécifie une valeur skip_rows non négative de type INT64 et seules les lignes correspondant à ce décalage seront prises en compte dans la table.

Ces clauses n'acceptent que les valeurs littérales ou de paramètres.

Les lignes renvoyées par LIMIT et OFFSET ne sont pas spécifiées, sauf si ces opérateurs sont utilisés après ORDER BY.

Alias

Un alias est un nom temporaire attribué à une table, une colonne ou une expression présente dans une requête. Vous pouvez introduire des alias explicites dans la liste SELECT ou la clause FROM, ou bien Cloud Spanner SQL déduira un alias implicite pour certaines expressions. Les expressions sans alias explicite ou implicite sont anonymes et la requête ne peut pas y faire référence par leur nom.

Syntaxe des alias explicites

Vous pouvez introduire des alias explicites dans la clause FROM ou dans la liste SELECT.

Dans une clause FROM, vous pouvez introduire des alias explicites pour tout élément, y compris les tables, les tableaux, les sous-requêtes et les clauses UNNEST, à l'aide d'un [AS] alias. Le mot clé AS est facultatif.

Exemple :

SELECT s.FirstName, s2.SongName
FROM Singers AS s, (SELECT * FROM Songs) AS s2;

Vous pouvez introduire des alias explicites pour toute expression de la liste SELECT en utilisant un [AS] alias. Le mot clé AS est facultatif.

Exemple :

SELECT s.FirstName AS name, LOWER(s.FirstName) AS lname
FROM Singers s;

Visibilité des alias explicite

Une fois que vous avez introduit un alias explicite dans une requête, des restrictions s'appliquent aux autres endroits où vous pouvez y faire référence. Ces restrictions sur la visibilité des alias sont le résultat des règles de champ d'application des noms Cloud Spanner SQL.

Alias de clause FROM

Cloud Spanner SQL traite les alias dans une clause FROM de gauche à droite, et les alias ne sont visibles que pour les expressions de chemin ultérieures dans une clause FROM.

Exemple :

Supposons que la table Singers contienne une colonne Concerts de type ARRAY.

SELECT FirstName
FROM Singers AS s, s.Concerts;

Incorrect :

SELECT FirstName
FROM s.Concerts, Singers AS s;  // INVALID.

Les alias de la clause FROM ne sont pas visibles pour les sous-requêtes d'une même clause FROM. Les sous-requêtes d'une clause FROM ne peuvent pas contenir de références corrélées à d'autres tables de la même clause FROM.

Incorrect :

SELECT FirstName
FROM Singers AS s, (SELECT (2020 - ReleaseDate) FROM s)  // INVALID.

Vous pouvez utiliser n'importe quel nom de colonne d'une table de FROM comme alias n'importe où dans la requête, avec ou sans qualification de nom de table.

Exemple :

SELECT FirstName, s.ReleaseDate
FROM Singers s WHERE ReleaseDate = 1975;

Si la clause FROM contient un alias explicite, vous devez utiliser ce dernier à la place de l'alias implicite pour le reste de la requête. (Consultez la section Alias implicites.) Un alias de table est utile par souci de brièveté ou pour éliminer toute ambiguïté; en cas d'autojointures par exemple, lorsque la même table est analysée plusieurs fois au cours du traitement de la requête.

Exemple :

SELECT * FROM Singers as s, Songs as s2
ORDER BY s.LastName

Incorrect. ORDER BY n'utilise pas l'alias de table :

SELECT * FROM Singers as s, Songs as s2
ORDER BY Singers.LastName;  // INVALID.

Alias de liste SELECT

Les alias de la liste SELECT sont visibles uniquement pour les clauses suivantes :

  • Clause GROUP BY
  • Clause ORDER BY
  • Clause HAVING

Exemple :

SELECT LastName AS last, SingerID
FROM Singers
ORDER BY last;

Alias explicites dans les clauses GROUP BY, ORDER BY et HAVING

Ces trois clauses, GROUP BY , ORDER BY et HAVING, ne peuvent faire référence qu'aux valeurs suivantes :

  • Aux tables de la clause FROM et à toutes leurs colonnes
  • Aux alias de la liste SELECT

GROUP BY et ORDER BY peuvent également faire référence à un troisième groupe :

  • Les littéraux entiers, qui font référence aux éléments de la liste SELECT. Le nombre entier 1 fait référence au premier élément de la liste SELECT, 2 au deuxième élément, etc.

Exemple :

SELECT SingerID AS sid, COUNT(Songid) AS s2id
FROM Songs
GROUP BY 1
ORDER BY 2 DESC;

La requête ci-dessus est équivalente à :

SELECT SingerID AS sid, COUNT(Songid) AS s2id
FROM Songs
GROUP BY sid
ORDER BY s2id DESC;

Alias ambigus

Cloud Spanner SQL génère une erreur si un nom est ambigu, ce qui signifie qu'il peut être résolu en plusieurs objets uniques.

Exemples :

Cette requête contient des noms de colonne de table en conflit, car Singers et Songs ont tous les deux une colonne nommée SingerID :

SELECT SingerID
FROM Singers, Songs;

Cette requête contient des alias ambigus dans la clause GROUP BY, car ils sont dupliqués dans la liste SELECT :

SELECT FirstName AS name, LastName AS name,
FROM Singers
GROUP BY name;

Il existe une ambiguïté entre un nom de colonne de la clause FROM et un alias de liste SELECT dans GROUP BY :

SELECT UPPER(LastName) AS LastName
FROM Singers
GROUP BY LastName;

La requête ci-dessus est ambiguë et générera une erreur, car LastName dans la clause GROUP BY peut faire référence à la colonne d'origine LastName dans Singers ou à l'alias AS LastName, dont la valeur est UPPER(LastName).

Les mêmes règles d'ambiguïté s'appliquent aux expressions de chemin d'accès. Considérez la requête suivante où la table contient les colonnes x et y, et où la colonne z est de type STRUCT et comporte les champs v, w et x.

Exemple :

SELECT x, z AS T
FROM table T
GROUP BY T.x;

L'alias T est ambigu et produit une erreur, car T.x dans la clause GROUP BY pourrait faire référence à table.x ou table.z.x.

Un nom n'est pas ambigu dans GROUP BY, ORDER BY ou HAVING s'il s'agit à la fois d'un nom de colonne et d'un alias de liste SELECT, à condition que le nom soit résolu sous la forme d'un objet sous-jacent identique.

Exemple :

SELECT LastName, BirthYear AS BirthYear
FROM Singers
GROUP BY BirthYear;

L'alias BirthYear n'est pas ambigu, car il renvoie à la même colonne sous-jacente, Singers.BirthYear.

Alias implicites

Dans la liste SELECT, s'il existe une expression ne comportant pas d'alias explicite, Cloud Spanner SQL attribue un alias implicite conformément aux règles suivantes. La liste SELECT peut contenir plusieurs colonnes avec le même alias.

  • Dans les identifiants, l'alias fait office d'identifiant. Par exemple, SELECT abc implique AS abc.
  • Dans les expressions de chemin, l'alias est le dernier identifiant du chemin. Par exemple, SELECT abc.def.ghi implique AS ghi.
  • Dans l'accès aux champs à l'aide de l'opérateur d'accès au champ membre "dot", l'alias est le nom du champ. Par exemple, SELECT (struct_function()).fname implique AS fname.

Dans tous les autres cas, il n'existe pas d'alias implicite, la colonne est donc anonyme et ne peut pas être référencée par nom. Les données de cette colonne seront tout de même renvoyées et les résultats de la requête affichés peuvent inclure un libellé généré pour cette colonne, mais celui-ci ne pourra pas être utilisé comme alias.

Dans une clause FROM, les éléments from_item ne sont pas tenus de contenir un alias. Les règles suivantes s'appliquent :

  • Si une expression sans alias explicite existe, Cloud Spanner SQL attribue un alias implicite dans les cas suivants :
    • Dans les identifiants, l'alias fait office d'identifiant. Par exemple, FROM abc implique AS abc.
    • Dans les expressions de chemin, l'alias est le dernier identifiant du chemin. Par exemple, FROM abc.def.ghi implique AS ghi.
    • La colonne produite à l'aide de WITH OFFSET possède l'alias implicite offset.

  • Les sous-requêtes de table n'ont pas d'alias implicite.
  • FROM UNNEST(x) n'a pas d'alias implicite.

Annexe A : illustrations avec des exemples de données

Exemples de tables

Les trois tables suivantes contiennent des exemples de données sur les athlètes, leurs écoles et les points qu'ils ont marqués pendant la saison. Ces tables seront utilisées pour illustrer le comportement de différentes clauses de requête.

Table Roster :

LastName SchoolID
Adams 50
Buchanan 52
Coolidge 52
Davis 51
Eisenhower 77

La table Roster comprend une liste de noms de joueurs (LastName) et l'identifiant unique attribué à leur école (SchoolID).

Table PlayerStats :

LastName OpponentID PointsScored
Adams 51 3
Buchanan 77 0
Coolidge 77 1
Adams 52 4
Buchanan 50 13

La table PlayerStats comprend une liste de noms de joueurs (LastName) et l'identifiant unique attribué à l'adversaire qu'ils ont affronté dans une partie donnée (OpponentID) ainsi que le nombre de points obtenus par l'athlète lors de cette partie (PointsScored).

Table TeamMascot :

SchoolId Mascot
50 Jaguars
51 Knights
52 Lakers
53 Mustangs

La table TeamMascot comprend une liste d'identifiants d'école uniques (SchoolID) et la mascotte de cette école (Mascot).

Types de jointures

1) JOINTURE [INTERNE]

Exemple :

SELECT * FROM Roster JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

Résultats :

LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Buchanan 52 52 Lakers
Coolidge 52 52 Lakers
Davis 51 51 Knights

2) JOINTURE CROISÉE

Exemple :

SELECT * FROM Roster CROSS JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

Résultats :

LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Adams 50 51 Knights
Adams 50 52 Lakers
Adams 50 53 Mustangs
Buchanan 52 50 Jaguars
Buchanan 52 51 Knights
Buchanan 52 52 Lakers
Buchanan 52 53 Mustangs
Coolidge 52 50 Jaguars
Coolidge 52 51 Knights
Coolidge 52 52 Lakers
Coolidge 52 53 Mustangs
Davis 51 50 Jaguars
Davis 51 51 Knights
Davis 51 52 Lakers
Davis 51 53 Mustangs
Eisenhower 77 50 Jaguars
Eisenhower 77 51 Knights
Eisenhower 77 52 Lakers
Eisenhower 77 53 Mustangs

3) JOINTURE [EXTERNE] COMPLÈTE

Exemple :

SELECT * FROM Roster FULL JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;
LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Buchanan 52 52 Lakers
Coolidge 52 52 Lakers
Davis 51 51 Knights
Eisenhower 77 NULL NULL
NULL NULL 53 Mustangs

4) JOINTURE [EXTERNE] GAUCHE

Exemple :

SELECT * FROM Roster LEFT JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

Résultats :

LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Buchanan 52 52 Lakers
Coolidge 52 52 Lakers
Davis 51 51 Knights
Eisenhower 77 NULL NULL

5) JOINTURE [EXTERNE] DROITE

Exemple :

SELECT * FROM Roster RIGHT JOIN TeamMascot
ON Roster.SchoolID = TeamMascot.SchoolID;

Résultats :

LastName Roster.SchoolId TeamMascot.SchoolId Mascot
Adams 50 50 Jaguars
Davis 51 51 Knights
Coolidge 52 52 Lakers
Buchanan 52 52 Lakers
NULL NULL 53 Mustangs

Clause GROUP BY

Exemple :

SELECT LastName, SUM(PointsScored)
FROM PlayerStats
GROUP BY LastName;
LastName SUM
Adams 7
Buchanan 13
Coolidge 1

Opérateurs d'ensemble

UNION

L'opérateur UNION combine les ensembles de résultats d'au moins deux instructions SELECT en associant des colonnes de l'ensemble de résultats de chaque instruction SELECT et en les concaténant verticalement.

Exemple :

SELECT Mascot AS X, SchoolID AS Y
FROM TeamMascot
UNION ALL
SELECT LastName, PointsScored
FROM PlayerStats;

Résultats :

X Y
Jaguars 50
Knights 51
Lakers 52
Mustangs 53
Adams 3
Buchanan 0
Coolidge 1
Adams 4
Buchanan 13

INTERSECT

Cette requête renvoie les noms de famille présents dans Roster et PlayerStats.

SELECT LastName
FROM Roster
INTERSECT ALL
SELECT LastName
FROM PlayerStats;

Résultats :

LastName
Adams
Coolidge
Buchanan

EXCEPT

La requête ci-dessous renvoie les noms de famille de la liste qui ne sont pas présents dans PlayerStats.

SELECT LastName
FROM Roster
EXCEPT DISTINCT
SELECT LastName
FROM PlayerStats;

Résultats :

LastName
Eisenhower
Davis

Si vous inversez l'ordre des instructions SELECT, les noms présents dans PlayerStats et non présents dans Roster seront renvoyés :

SELECT LastName
FROM PlayerStats
EXCEPT DISTINCT
SELECT LastName
FROM Roster;

Résultats :

(empty)

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Documentation Cloud Spanner