> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Documentation de la clause ARRAY JOIN

# Clause ARRAY JOIN

Pour les tables qui contiennent une colonne de type Array, il est courant de produire une nouvelle table comportant une ligne pour chaque élément du tableau de cette colonne initiale, tandis que les valeurs des autres colonnes sont dupliquées. Il s'agit du cas de base de ce que fait la clause `ARRAY JOIN`.

Son nom vient du fait qu'on peut la considérer comme l'exécution d'un `JOIN` avec un tableau ou une structure de données imbriquée. L'objectif est similaire à celui de la fonction [arrayJoin](/fr/reference/functions/regular-functions/array-join), mais la fonctionnalité de la clause est plus large.

Syntaxe :

```sql theme={null}
SELECT <expr_list>
FROM <left_subquery>
[LEFT] ARRAY JOIN <array>
[WHERE|PREWHERE <expr>]
...
```

Les types de `ARRAY JOIN` pris en charge sont listés ci-dessous :

* `ARRAY JOIN` - Dans le cas de base, les tableaux vides ne sont pas inclus dans le résultat du `JOIN`.
* `LEFT ARRAY JOIN` - Le résultat du `JOIN` contient des lignes avec des tableaux vides. La valeur d’un tableau vide est définie sur la valeur par défaut du type d’élément du tableau (généralement 0, une chaîne vide ou NULL).

<div id="basic-array-join-examples">
  ## Exemples de base d’ARRAY JOIN
</div>

<div id="array-join-left-array-join-examples">
  ### ARRAY JOIN et LEFT ARRAY JOIN
</div>

Les exemples ci-dessous illustrent l’utilisation des clauses `ARRAY JOIN` et `LEFT ARRAY JOIN`. Créons une table avec une colonne de type [Array](/fr/reference/data-types/array) et insérons-y des valeurs :

```sql theme={null}
CREATE TABLE arrays_test
(
    s String,
    arr Array(UInt8)
) ENGINE = Memory;

INSERT INTO arrays_test
VALUES ('Hello', [1,2]), ('World', [3,4,5]), ('Goodbye', []);
```

```response theme={null}
┌─s───────────┬─arr─────┐
│ Hello       │ [1,2]   │
│ World       │ [3,4,5] │
│ Goodbye     │ []      │
└─────────────┴─────────┘
```

L’exemple ci-dessous utilise la clause `ARRAY JOIN` :

```sql theme={null}
SELECT s, arr
FROM arrays_test
ARRAY JOIN arr;
```

```response theme={null}
┌─s─────┬─arr─┐
│ Hello │   1 │
│ Hello │   2 │
│ World │   3 │
│ World │   4 │
│ World │   5 │
└───────┴─────┘
```

L’exemple suivant utilise la clause `LEFT ARRAY JOIN` :

```sql theme={null}
SELECT s, arr
FROM arrays_test
LEFT ARRAY JOIN arr;
```

```response theme={null}
┌─s───────────┬─arr─┐
│ Hello       │   1 │
│ Hello       │   2 │
│ World       │   3 │
│ World       │   4 │
│ World       │   5 │
│ Goodbye     │   0 │
└─────────────┴─────┘
```

<div id="array-join-arrayEnumerate">
  ### ARRAY JOIN et la fonction arrayEnumerate
</div>

Cette fonction est généralement utilisée avec `ARRAY JOIN`. Elle permet de ne compter quelque chose qu'une seule fois par tableau après l’application de `ARRAY JOIN`. Exemple :

```sql theme={null}
SELECT
    count() AS Reaches,
    countIf(num = 1) AS Hits
FROM test.hits
ARRAY JOIN
    GoalsReached,
    arrayEnumerate(GoalsReached) AS num
WHERE CounterID = 160656
LIMIT 10
```

```text theme={null}
┌─Reaches─┬──Hits─┐
│   95606 │ 31406 │
└─────────┴───────┘
```

Dans cet exemple, Reaches correspond au nombre de conversions (les chaînes obtenues après application de `ARRAY JOIN`), et Hits au nombre de pages vues (les chaînes avant `ARRAY JOIN`). Dans ce cas précis, vous pouvez obtenir le même résultat plus simplement :

```sql theme={null}
SELECT
    sum(length(GoalsReached)) AS Reaches,
    count() AS Hits
FROM test.hits
WHERE (CounterID = 160656) AND notEmpty(GoalsReached)
```

```text theme={null}
┌─Reaches─┬──Hits─┐
│   95606 │ 31406 │
└─────────┴───────┘
```

<div id="array_join_arrayEnumerateUniq">
  ### ARRAY JOIN et arrayEnumerateUniq
</div>

Cette fonction est utile lorsque l'on utilise `ARRAY JOIN` et que l'on agrège des éléments de tableau.

Dans cet exemple, pour chaque ID d'objectif, on calcule le nombre de conversions (chaque élément de la structure de données imbriquée Goals est un objectif atteint, que nous appelons une conversion) ainsi que le nombre de sessions. Sans `ARRAY JOIN`, nous aurions compté le nombre de sessions avec sum(Sign). Mais dans ce cas précis, les lignes ont été multipliées par la structure imbriquée Goals ; afin de ne compter chaque session qu'une seule fois ensuite, nous appliquons une condition à la valeur de la fonction `arrayEnumerateUniq(Goals.ID)`.

```sql theme={null}
SELECT
    Goals.ID AS GoalID,
    sum(Sign) AS Reaches,
    sumIf(Sign, num = 1) AS Visits
FROM test.visits
ARRAY JOIN
    Goals,
    arrayEnumerateUniq(Goals.ID) AS num
WHERE CounterID = 160656
GROUP BY GoalID
ORDER BY Reaches DESC
LIMIT 10
```

```text theme={null}
┌──GoalID─┬─Reaches─┬─Visits─┐
│   53225 │    3214 │   1097 │
│ 2825062 │    3188 │   1097 │
│   56600 │    2803 │    488 │
│ 1989037 │    2401 │    365 │
│ 2830064 │    2396 │    910 │
│ 1113562 │    2372 │    373 │
│ 3270895 │    2262 │    812 │
│ 1084657 │    2262 │    345 │
│   56599 │    2260 │    799 │
│ 3271094 │    2256 │    812 │
└─────────┴─────────┴────────┘
```

<div id="using-aliases">
  ## Utilisation des alias
</div>

Un alias peut être défini pour un tableau dans la clause `ARRAY JOIN`. Dans ce cas, on peut accéder à un élément du tableau via cet alias, tandis que le tableau lui-même reste accessible par son nom d'origine. Exemple :

```sql theme={null}
SELECT s, arr, a
FROM arrays_test
ARRAY JOIN arr AS a;
```

```response theme={null}
┌─s─────┬─arr─────┬─a─┐
│ Hello │ [1,2]   │ 1 │
│ Hello │ [1,2]   │ 2 │
│ World │ [3,4,5] │ 3 │
│ World │ [3,4,5] │ 4 │
│ World │ [3,4,5] │ 5 │
└───────┴─────────┴───┘
```

À l’aide d’alias, vous pouvez effectuer `ARRAY JOIN` avec un tableau externe. Par exemple :

```sql theme={null}
SELECT s, arr_external
FROM arrays_test
ARRAY JOIN [1, 2, 3] AS arr_external;
```

```response theme={null}
┌─s───────────┬─arr_external─┐
│ Hello       │            1 │
│ Hello       │            2 │
│ Hello       │            3 │
│ World       │            1 │
│ World       │            2 │
│ World       │            3 │
│ Goodbye     │            1 │
│ Goodbye     │            2 │
│ Goodbye     │            3 │
└─────────────┴──────────────┘
```

Plusieurs tableaux peuvent être séparés par des virgules dans la clause `ARRAY JOIN`. Dans ce cas, `JOIN` leur est appliqué simultanément (somme directe, et non produit cartésien). Notez que, par défaut, tous les tableaux doivent avoir la même taille. Exemple :

```sql theme={null}
SELECT s, arr, a, num, mapped
FROM arrays_test
ARRAY JOIN arr AS a, arrayEnumerate(arr) AS num, arrayMap(x -> x + 1, arr) AS mapped;
```

```response theme={null}
┌─s─────┬─arr─────┬─a─┬─num─┬─mapped─┐
│ Hello │ [1,2]   │ 1 │   1 │      2 │
│ Hello │ [1,2]   │ 2 │   2 │      3 │
│ World │ [3,4,5] │ 3 │   1 │      4 │
│ World │ [3,4,5] │ 4 │   2 │      5 │
│ World │ [3,4,5] │ 5 │   3 │      6 │
└───────┴─────────┴───┴─────┴────────┘
```

L’exemple ci-dessous utilise la fonction [arrayEnumerate](/fr/reference/functions/regular-functions/array-functions#arrayEnumerate) :

```sql theme={null}
SELECT s, arr, a, num, arrayEnumerate(arr)
FROM arrays_test
ARRAY JOIN arr AS a, arrayEnumerate(arr) AS num;
```

```response theme={null}
┌─s─────┬─arr─────┬─a─┬─num─┬─arrayEnumerate(arr)─┐
│ Hello │ [1,2]   │ 1 │   1 │ [1,2]               │
│ Hello │ [1,2]   │ 2 │   2 │ [1,2]               │
│ World │ [3,4,5] │ 3 │   1 │ [1,2,3]             │
│ World │ [3,4,5] │ 4 │   2 │ [1,2,3]             │
│ World │ [3,4,5] │ 5 │   3 │ [1,2,3]             │
└───────┴─────────┴───┴─────┴─────────────────────┘
```

Plusieurs tableaux de tailles différentes peuvent être joints à l’aide de : `SETTINGS enable_unaligned_array_join = 1`. Exemple :

```sql theme={null}
SELECT s, arr, a, b
FROM arrays_test ARRAY JOIN arr AS a, [['a','b'],['c']] AS b
SETTINGS enable_unaligned_array_join = 1;
```

```response theme={null}
┌─s───────┬─arr─────┬─a─┬─b─────────┐
│ Hello   │ [1,2]   │ 1 │ ['a','b'] │
│ Hello   │ [1,2]   │ 2 │ ['c']     │
│ World   │ [3,4,5] │ 3 │ ['a','b'] │
│ World   │ [3,4,5] │ 4 │ ['c']     │
│ World   │ [3,4,5] │ 5 │ []        │
│ Goodbye │ []      │ 0 │ ['a','b'] │
│ Goodbye │ []      │ 0 │ ['c']     │
└─────────┴─────────┴───┴───────────┘
```

<div id="array-join-with-nested-data-structure">
  ## ARRAY JOIN avec une structure de données imbriquée
</div>

`ARRAY JOIN` fonctionne également avec les [structures de données imbriquées](/fr/reference/data-types/nested-data-structures/index) :

```sql theme={null}
CREATE TABLE nested_test
(
    s String,
    nest Nested(
    x UInt8,
    y UInt32)
) ENGINE = Memory;

INSERT INTO nested_test
VALUES ('Hello', [1,2], [10,20]), ('World', [3,4,5], [30,40,50]), ('Goodbye', [], []);
```

```response theme={null}
┌─s───────┬─nest.x──┬─nest.y─────┐
│ Hello   │ [1,2]   │ [10,20]    │
│ World   │ [3,4,5] │ [30,40,50] │
│ Goodbye │ []      │ []         │
└─────────┴─────────┴────────────┘
```

```sql theme={null}
SELECT s, `nest.x`, `nest.y`
FROM nested_test
ARRAY JOIN nest;
```

```response theme={null}
┌─s─────┬─nest.x─┬─nest.y─┐
│ Hello │      1 │     10 │
│ Hello │      2 │     20 │
│ World │      3 │     30 │
│ World │      4 │     40 │
│ World │      5 │     50 │
└───────┴────────┴────────┘
```

Lorsque vous spécifiez les noms de structures de données imbriquées dans `ARRAY JOIN`, cela a le même sens qu’un `ARRAY JOIN` appliqué à tous les éléments de tableau qui la composent. Des exemples sont présentés ci-dessous :

```sql theme={null}
SELECT s, `nest.x`, `nest.y`
FROM nested_test
ARRAY JOIN `nest.x`, `nest.y`;
```

```response theme={null}
┌─s─────┬─nest.x─┬─nest.y─┐
│ Hello │      1 │     10 │
│ Hello │      2 │     20 │
│ World │      3 │     30 │
│ World │      4 │     40 │
│ World │      5 │     50 │
└───────┴────────┴────────┘
```

Cette variante est également valable :

```sql theme={null}
SELECT s, `nest.x`, `nest.y`
FROM nested_test
ARRAY JOIN `nest.x`;
```

```response theme={null}
┌─s─────┬─nest.x─┬─nest.y─────┐
│ Hello │      1 │ [10,20]    │
│ Hello │      2 │ [10,20]    │
│ World │      3 │ [30,40,50] │
│ World │      4 │ [30,40,50] │
│ World │      5 │ [30,40,50] │
└───────┴────────┴────────────┘
```

Un alias peut être utilisé pour une structure de données imbriquée afin de sélectionner soit le résultat du `JOIN`, soit le tableau source. Exemple :

```sql theme={null}
SELECT s, `n.x`, `n.y`, `nest.x`, `nest.y`
FROM nested_test
ARRAY JOIN nest AS n;
```

```response theme={null}
┌─s─────┬─n.x─┬─n.y─┬─nest.x──┬─nest.y─────┐
│ Hello │   1 │  10 │ [1,2]   │ [10,20]    │
│ Hello │   2 │  20 │ [1,2]   │ [10,20]    │
│ World │   3 │  30 │ [3,4,5] │ [30,40,50] │
│ World │   4 │  40 │ [3,4,5] │ [30,40,50] │
│ World │   5 │  50 │ [3,4,5] │ [30,40,50] │
└───────┴─────┴─────┴─────────┴────────────┘
```

Exemple d’utilisation de la fonction [arrayEnumerate](/fr/reference/functions/regular-functions/array-functions#arrayEnumerate) :

```sql theme={null}
SELECT s, `n.x`, `n.y`, `nest.x`, `nest.y`, num
FROM nested_test
ARRAY JOIN nest AS n, arrayEnumerate(`nest.x`) AS num;
```

```response theme={null}
┌─s─────┬─n.x─┬─n.y─┬─nest.x──┬─nest.y─────┬─num─┐
│ Hello │   1 │  10 │ [1,2]   │ [10,20]    │   1 │
│ Hello │   2 │  20 │ [1,2]   │ [10,20]    │   2 │
│ World │   3 │  30 │ [3,4,5] │ [30,40,50] │   1 │
│ World │   4 │  40 │ [3,4,5] │ [30,40,50] │   2 │
│ World │   5 │  50 │ [3,4,5] │ [30,40,50] │   3 │
└───────┴─────┴─────┴─────────┴────────────┴─────┘
```

<div id="implementation-details">
  ## Détails d’implémentation
</div>

L’ordre d’exécution des requêtes est optimisé lors de l’utilisation de `ARRAY JOIN`. Bien que `ARRAY JOIN` doive toujours être spécifié avant la clause [WHERE](/fr/reference/statements/select/where)/[PREWHERE](/fr/reference/statements/select/prewhere) dans une requête, leur exécution peut techniquement se faire dans n’importe quel ordre, sauf si le résultat de `ARRAY JOIN` est utilisé pour le filtrage. L’ordre de traitement est contrôlé par l’optimiseur de requêtes.

<div id="incompatibility-with-short-circuit-function-evaluation">
  ### Incompatibilité avec l’évaluation court-circuitée des fonctions
</div>

[L’évaluation court-circuitée des fonctions](/fr/reference/settings/session-settings#short_circuit_function_evaluation) est une fonctionnalité qui optimise l’exécution d’expressions complexes dans certaines fonctions telles que `if`, `multiIf`, `and` et `or`. Elle évite que des exceptions potentielles, comme une division par zéro, ne surviennent lors de l’exécution de ces fonctions.

`arrayJoin` est toujours exécutée et n’est pas compatible avec l’évaluation court-circuitée des fonctions. Cela s’explique par le fait qu’il s’agit d’une fonction particulière, traitée séparément de toutes les autres fonctions lors de l’analyse et de l’exécution de la requête, et qu’elle nécessite une logique supplémentaire incompatible avec l’exécution court-circuitée des fonctions. En effet, le nombre de lignes dans le résultat dépend du résultat de `arrayJoin`, et il est trop complexe et coûteux d’implémenter une exécution paresseuse de `arrayJoin`.

<div id="related-content">
  ## Articles connexes
</div>

* Blog : [Travailler avec des séries temporelles dans ClickHouse](https://clickhouse.com/blog/working-with-time-series-data-and-functions-ClickHouse)
