> ## 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.

> Apprenez à connecter pg_clickhouse à ClickHouse et à interroger un jeu de données d’exemple sur les taxis new-yorkais.

# Tutoriel pg_clickhouse

<div id="overview">
  ## Vue d’ensemble
</div>

Ce tutoriel suit le \[tutoriel ClickHouse], mais exécute toutes ses requêtes via
pg\_clickhouse.

<div id="start-clickhouse">
  ## Démarrer ClickHouse
</div>

Commencez par créer une base de données ClickHouse si vous n’en avez pas déjà. Pour démarrer rapidement,
vous pouvez utiliser l’image Docker :

```sh theme={null}
docker run -d --network host --name clickhouse -p 8123:8123 -p9000:9000 --ulimit nofile=262144:262144 clickhouse
docker exec -it clickhouse clickhouse-client
```

<div id="create-a-table">
  ## Créer une table
</div>

Inspirons-nous du \[tutoriel ClickHouse] pour créer une base de données simple à partir du jeu de données des taxis de la ville de New York :

```sql theme={null}
CREATE DATABASE taxi;
CREATE TABLE taxi.trips
(
    trip_id UInt32,
    vendor_id Enum8(
        '1'      =  1, '2'      =  2, '3'      =  3, '4'      =  4,
        'CMT'    =  5, 'VTS'    =  6, 'DDS'    =  7, 'B02512' = 10,
        'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14,
        ''       = 15
    ),
    pickup_date Date,
    pickup_datetime DateTime,
    dropoff_date Date,
    dropoff_datetime DateTime,
    store_and_fwd_flag UInt8,
    rate_code_id UInt8,
    pickup_longitude Float64,
    pickup_latitude Float64,
    dropoff_longitude Float64,
    dropoff_latitude Float64,
    passenger_count UInt8,
    trip_distance Float64,
    fare_amount Decimal(10, 2),
    extra Decimal(10, 2),
    mta_tax Decimal(10, 2),
    tip_amount Decimal(10, 2),
    tolls_amount Decimal(10, 2),
    ehail_fee Decimal(10, 2),
    improvement_surcharge Decimal(10, 2),
    total_amount Decimal(10, 2),
    payment_type Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),
    trip_type UInt8,
    pickup FixedString(25),
    dropoff FixedString(25),
    cab_type Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),
    pickup_nyct2010_gid Int8,
    pickup_ctlabel Float32,
    pickup_borocode Int8,
    pickup_ct2010 String,
    pickup_boroct2010 String,
    pickup_cdeligibil String,
    pickup_ntacode FixedString(4),
    pickup_ntaname String,
    pickup_puma UInt16,
    dropoff_nyct2010_gid UInt8,
    dropoff_ctlabel Float32,
    dropoff_borocode UInt8,
    dropoff_ct2010 String,
    dropoff_boroct2010 String,
    dropoff_cdeligibil String,
    dropoff_ntacode FixedString(4),
    dropoff_ntaname String,
    dropoff_puma UInt16
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(pickup_date)
ORDER BY pickup_datetime;
```

<div id="add-the-data-set">
  ## Ajouter le jeu de données
</div>

Importez ensuite les données :

```sql theme={null}
INSERT INTO taxi.trips
SELECT * FROM s3(
    'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/trips_{1..2}.gz',
    'TabSeparatedWithNames', "
    trip_id UInt32,
    vendor_id Enum8(
        '1'      =  1, '2'      =  2, '3'      =  3, '4'      =  4,
        'CMT'    =  5, 'VTS'    =  6, 'DDS'    =  7, 'B02512' = 10,
        'B02598' = 11, 'B02617' = 12, 'B02682' = 13, 'B02764' = 14,
        ''       = 15
    ),
    pickup_date Date,
    pickup_datetime DateTime,
    dropoff_date Date,
    dropoff_datetime DateTime,
    store_and_fwd_flag UInt8,
    rate_code_id UInt8,
    pickup_longitude Float64,
    pickup_latitude Float64,
    dropoff_longitude Float64,
    dropoff_latitude Float64,
    passenger_count UInt8,
    trip_distance Float64,
    fare_amount Decimal(10, 2),
    extra Decimal(10, 2),
    mta_tax Decimal(10, 2),
    tip_amount Decimal(10, 2),
    tolls_amount Decimal(10, 2),
    ehail_fee Decimal(10, 2),
    improvement_surcharge Decimal(10, 2),
    total_amount Decimal(10, 2),
    payment_type Enum8('UNK' = 0, 'CSH' = 1, 'CRE' = 2, 'NOC' = 3, 'DIS' = 4),
    trip_type UInt8,
    pickup FixedString(25),
    dropoff FixedString(25),
    cab_type Enum8('yellow' = 1, 'green' = 2, 'uber' = 3),
    pickup_nyct2010_gid Int8,
    pickup_ctlabel Float32,
    pickup_borocode Int8,
    pickup_ct2010 String,
    pickup_boroct2010 String,
    pickup_cdeligibil String,
    pickup_ntacode FixedString(4),
    pickup_ntaname String,
    pickup_puma UInt16,
    dropoff_nyct2010_gid UInt8,
    dropoff_ctlabel Float32,
    dropoff_borocode UInt8,
    dropoff_ct2010 String,
    dropoff_boroct2010 String,
    dropoff_cdeligibil String,
    dropoff_ntacode FixedString(4),
    dropoff_ntaname String,
    dropoff_puma UInt16
") SETTINGS input_format_try_infer_datetimes = 0
```

Vérifiez que nous pouvons l’interroger, puis quittez le client :

```sql theme={null}
SELECT count() FROM taxi.trips;
quit
```

<div id="install-pg_clickhouse">
  ### Installer pg\_clickhouse
</div>

Compilez et installez pg\_clickhouse depuis [PGXN] ou [GitHub]. Vous pouvez aussi démarrer un
conteneur Docker à partir de l’\[image pg\_clickhouse], qui ajoute simplement
pg\_clickhouse à l’\[image Postgres] Docker :

```sh theme={null}
docker run -d --network host --name pg_clickhouse -e POSTGRES_PASSWORD=my_pass \
       -d ghcr.io/clickhouse/pg_clickhouse:18
```

<div id="connect-pg_clickhouse">
  ### Connecter pg\_clickhouse
</div>

Connectez-vous maintenant à Postgres :

```sh theme={null}
docker exec -it pg_clickhouse psql -U postgres
```

Puis créez pg\_clickhouse :

```sql theme={null}
CREATE EXTENSION pg_clickhouse;
```

Créez un foreign server à l’aide du nom d’hôte, du port et du nom de la base de données de votre
base ClickHouse.

```sql theme={null}
CREATE SERVER taxi_srv FOREIGN DATA WRAPPER clickhouse_fdw
       OPTIONS(driver 'binary', host 'localhost', dbname 'taxi');
```

Ici, nous avons choisi d'utiliser le driver binaire, qui utilise le protocole
binaire de ClickHouse. Vous pouvez également utiliser le driver "http", qui utilise l'interface HTTP.

Ensuite, mappez un utilisateur PostgreSQL à un utilisateur ClickHouse. Le moyen le plus simple de procéder
consiste à associer l'utilisateur PostgreSQL actuel à un utilisateur distant pour le
serveur foreign :

```sql theme={null}
CREATE USER MAPPING FOR CURRENT_USER SERVER taxi_srv
       OPTIONS (user 'default');
```

Vous pouvez également spécifier une option `password`.

Ajoutez maintenant la table taxi en important simplement toutes les tables de la base de données ClickHouse distante dans un schéma Postgres :

```sql theme={null}
CREATE SCHEMA taxi;
IMPORT FOREIGN SCHEMA taxi FROM SERVER taxi_srv INTO taxi;
```

Et maintenant, la table devrait être importée : dans [psql], utilisez `\det+` pour l’afficher :

```pgsql theme={null}
taxi=# \det+ taxi.*
                                       List of foreign tables
 Schema | Table |  Server  |                        FDW options                        | Description
--------+-------+----------+-----------------------------------------------------------+-------------
 taxi   | trips | taxi_srv | (database 'taxi', table_name 'trips', engine 'MergeTree') | [null]
(1 row)
```

C’est bon ! Utilisez `\d` pour afficher toutes les colonnes :

```pgsql theme={null}
taxi=# \d taxi.trips
                                   Foreign table "taxi.trips"
        Column         |           Type           | Collation | Nullable | Default | FDW options
-----------------------+--------------------------+-----------+----------+---------+-------------
 trip_id               | bigint                   |           | not null |         |
 vendor_id             | text                     |           | not null |         |
 pickup_date           | date                     |           | not null |         |
 pickup_datetime       | timestamp with time zone |           | not null |         |
 dropoff_date          | date                     |           | not null |         |
 dropoff_datetime      | timestamp with time zone |           | not null |         |
 store_and_fwd_flag    | smallint                 |           | not null |         |
 rate_code_id          | smallint                 |           | not null |         |
 pickup_longitude      | double precision         |           | not null |         |
 pickup_latitude       | double precision         |           | not null |         |
 dropoff_longitude     | double precision         |           | not null |         |
 dropoff_latitude      | double precision         |           | not null |         |
 passenger_count       | smallint                 |           | not null |         |
 trip_distance         | double precision         |           | not null |         |
 fare_amount           | numeric(10,2)            |           | not null |         |
 extra                 | numeric(10,2)            |           | not null |         |
 mta_tax               | numeric(10,2)            |           | not null |         |
 tip_amount            | numeric(10,2)            |           | not null |         |
 tolls_amount          | numeric(10,2)            |           | not null |         |
 ehail_fee             | numeric(10,2)            |           | not null |         |
 improvement_surcharge | numeric(10,2)            |           | not null |         |
 total_amount          | numeric(10,2)            |           | not null |         |
 payment_type          | text                     |           | not null |         |
 trip_type             | smallint                 |           | not null |         |
 pickup                | character varying(25)    |           | not null |         |
 dropoff               | character varying(25)    |           | not null |         |
 cab_type              | text                     |           | not null |         |
 pickup_nyct2010_gid   | smallint                 |           | not null |         |
 pickup_ctlabel        | real                     |           | not null |         |
 pickup_borocode       | smallint                 |           | not null |         |
 pickup_ct2010         | text                     |           | not null |         |
 pickup_boroct2010     | text                     |           | not null |         |
 pickup_cdeligibil     | text                     |           | not null |         |
 pickup_ntacode        | character varying(4)     |           | not null |         |
 pickup_ntaname        | text                     |           | not null |         |
 pickup_puma           | integer                  |           | not null |         |
 dropoff_nyct2010_gid  | smallint                 |           | not null |         |
 dropoff_ctlabel       | real                     |           | not null |         |
 dropoff_borocode      | smallint                 |           | not null |         |
 dropoff_ct2010        | text                     |           | not null |         |
 dropoff_boroct2010    | text                     |           | not null |         |
 dropoff_cdeligibil    | text                     |           | not null |         |
 dropoff_ntacode       | character varying(4)     |           | not null |         |
 dropoff_ntaname       | text                     |           | not null |         |
 dropoff_puma          | integer                  |           | not null |         |
Server: taxi_srv
FDW options: (database 'taxi', table_name 'trips', engine 'MergeTree')
```

Exécutez maintenant une requête sur la table :

```pgsql theme={null}
 SELECT count(*) FROM taxi.trips;
   count
 ---------
  1999657
 (1 row)
```

Notez la rapidité d’exécution de la requête. pg\_clickhouse transmet l’intégralité de la
requête, y compris l’agrégat `COUNT()`, à ClickHouse, de sorte qu’elle s’y exécute et ne
renvoie qu’une seule ligne à Postgres. Utilisez [EXPLAIN] pour le constater :

```pgsql theme={null}
 EXPLAIN select count(*) from taxi.trips;
                    QUERY PLAN
 -------------------------------------------------
  Foreign Scan  (cost=1.00..-0.90 rows=1 width=8)
    Relations: Aggregate on (trips)
 (2 rows)
```

Notez que "Foreign Scan" apparaît à la racine du plan, ce qui signifie que l’intégralité de la
requête a été déléguée à ClickHouse.

<div id="analyze-the-data">
  ## Analyser les données
</div>

Exécutez quelques requêtes pour analyser les données. Consultez les exemples suivants ou essayez
votre propre requête SQL.

* Calculez le montant moyen des pourboires :

  ```sql theme={null}
  taxi=# \timing
  Timing is on.
  taxi=# SELECT round(avg(tip_amount), 2) FROM taxi.trips;
   round
  -------
    1.68
  (1 row)

  Time: 9.438 ms
  ```

* Calculez le coût moyen selon le nombre de passagers :

  ```pgsql theme={null}
  taxi=# SELECT
          passenger_count,
          avg(total_amount)::NUMERIC(10, 2) AS average_total_amount
      FROM taxi.trips
      GROUP BY passenger_count;
   passenger_count | average_total_amount
  -----------------+----------------------
                 0 |                22.68
                 1 |                15.96
                 2 |                17.14
                 3 |                16.75
                 4 |                17.32
                 5 |                16.34
                 6 |                16.03
                 7 |                59.79
                 8 |                36.40
                 9 |                 9.79
  (10 rows)

  Time: 27.266 ms
  ```

* Calculez le nombre de prises en charge quotidiennes par quartier :

  ```pgsql theme={null}
  taxi=# SELECT
      pickup_date,
      pickup_ntaname,
      SUM(1) AS number_of_trips
  FROM taxi.trips
  GROUP BY pickup_date, pickup_ntaname
  ORDER BY pickup_date ASC LIMIT 10;
   pickup_date |         pickup_ntaname         | number_of_trips
  -------------+--------------------------------+-----------------
   2015-07-01  | Williamsburg                   |               1
   2015-07-01  | park-cemetery-etc-Queens       |               6
   2015-07-01  | Maspeth                        |               1
   2015-07-01  | Stuyvesant Town-Cooper Village |              44
   2015-07-01  | Rego Park                      |               1
   2015-07-01  | Greenpoint                     |               7
   2015-07-01  | Highbridge                     |               1
   2015-07-01  | Briarwood-Jamaica Hills        |               3
   2015-07-01  | Airport                        |             550
   2015-07-01  | East Harlem North              |              32
  (10 rows)

  Time: 30.978 ms
  ```

* Calculez la durée de chaque trajet en minutes, puis regroupez les résultats par
  durée du trajet :

  ```pgsql theme={null}
  taxi=# SELECT
      avg(tip_amount) AS avg_tip,
      avg(fare_amount) AS avg_fare,
      avg(passenger_count) AS avg_passenger,
      count(*) AS count,
      round((date_part('epoch', dropoff_datetime) - date_part('epoch', pickup_datetime)) / 60) as trip_minutes
  FROM taxi.trips
  WHERE round((date_part('epoch', dropoff_datetime) - date_part('epoch', pickup_datetime)) / 60) > 0
  GROUP BY trip_minutes
  ORDER BY trip_minutes DESC
  LIMIT 5;
        avg_tip      |     avg_fare     |  avg_passenger   | count | trip_minutes
  -------------------+------------------+------------------+-------+--------------
                1.96 |                8 |                1 |     1 |        27512
                   0 |               12 |                2 |     1 |        27500
   0.562727272727273 | 17.4545454545455 | 2.45454545454545 |    11 |         1440
   0.716564885496183 | 14.2786259541985 | 1.94656488549618 |   131 |         1439
    1.00945205479452 | 12.8787671232877 | 1.98630136986301 |   146 |         1438
  (5 rows)

  Time: 45.477 ms
  ```

* Affichez le nombre de prises en charge dans chaque quartier, réparti selon l’heure de la journée :

  ```pgsql theme={null}
  taxi=# SELECT
      pickup_ntaname,
      date_part('hour', pickup_datetime) as pickup_hour,
      SUM(1) AS pickups
  FROM taxi.trips
  WHERE pickup_ntaname != ''
  GROUP BY pickup_ntaname, pickup_hour
  ORDER BY pickup_ntaname, date_part('hour', pickup_datetime)
  LIMIT 5;
   pickup_ntaname | pickup_hour | pickups
  ----------------+-------------+---------
   Airport        |           0 |    3509
   Airport        |           1 |    1184
   Airport        |           2 |     401
   Airport        |           3 |     152
   Airport        |           4 |     213
  (5 rows)

  Time: 36.895 ms
  ```

* Définissez le fuseau horaire d’affichage sur celui de New York et récupérez les trajets vers les
  aéroports de LaGuardia ou JFK :

  ```pgsql theme={null}
  taxi=# SET timezone = 'America/New_York';
  SET
  taxi=# SELECT
      pickup_datetime,
      dropoff_datetime,
      total_amount,
      pickup_nyct2010_gid,
      dropoff_nyct2010_gid,
      CASE
          WHEN dropoff_nyct2010_gid = 138 THEN 'LGA'
          WHEN dropoff_nyct2010_gid = 132 THEN 'JFK'
      END AS airport_code,
      EXTRACT(YEAR FROM pickup_datetime) AS year,
      EXTRACT(DAY FROM pickup_datetime) AS day,
      EXTRACT(HOUR FROM pickup_datetime) AS hour
  FROM taxi.trips
  WHERE dropoff_nyct2010_gid IN (132, 138)
  ORDER BY pickup_datetime
  LIMIT 5;
      pickup_datetime     |    dropoff_datetime    | total_amount | pickup_nyct2010_gid | dropoff_nyct2010_gid | airport_code | year | day | hour
  ------------------------+------------------------+--------------+---------------------+----------------------+--------------+------+-----+------
   2015-06-30 20:04:14-04 | 2015-06-30 20:15:29-04 |        13.30 |                 -34 |                  132 | JFK          | 2015 |  30 |   20
   2015-06-30 20:09:42-04 | 2015-06-30 20:12:55-04 |         6.80 |                  50 |                  138 | LGA          | 2015 |  30 |   20
   2015-06-30 20:23:04-04 | 2015-06-30 20:24:39-04 |         4.80 |                -125 |                  132 | JFK          | 2015 |  30 |   20
   2015-06-30 20:27:51-04 | 2015-06-30 20:39:02-04 |        14.72 |                -101 |                  138 | LGA          | 2015 |  30 |   20
   2015-06-30 20:32:03-04 | 2015-06-30 20:55:39-04 |        39.34 |                  48 |                  138 | LGA          | 2015 |  30 |   20
  (5 rows)

  Time: 17.450 ms
  ```

<div id="create-a-dictionary">
  ## Créer un dictionnaire
</div>

Créez un dictionnaire associé à une table dans votre service ClickHouse. La
table et le dictionnaire sont basés sur un fichier CSV qui contient une ligne pour chaque
quartier de New York.

Les quartiers sont associés aux noms des cinq boroughs de New York
(Bronx, Brooklyn, Manhattan, Queens et Staten Island), ainsi qu'à l'aéroport de Newark
(EWR).

Voici un extrait du fichier CSV que vous utilisez, présenté sous forme de tableau. La
colonne `LocationID` du fichier correspond aux colonnes `pickup_nyct2010_gid` et
`dropoff_nyct2010_gid` de votre table des trajets :

| LocationID | Borough       | Zone                    | service\_zone |
| ---------: | ------------- | ----------------------- | ------------- |
|          1 | EWR           | Newark Airport          | EWR           |
|          2 | Queens        | Jamaica Bay             | Boro Zone     |
|          3 | Bronx         | Allerton/Pelham Gardens | Boro Zone     |
|          4 | Manhattan     | Alphabet City           | Yellow Zone   |
|          5 | Staten Island | Arden Heights           | Boro Zone     |

1. Toujours dans Postgres, utilisez la fonction `clickhouse_raw_query` pour créer un
   \[dictionnaire] ClickHouse nommé `taxi_zone_dictionary` et le renseigner à
   partir du fichier CSV stocké dans S3 :

   ```sql theme={null}
   SELECT clickhouse_raw_query($$
       CREATE DICTIONARY taxi.taxi_zone_dictionary (
           LocationID Int64 DEFAULT 0,
           Borough String,
           zone String,
           service_zone String
       )
       PRIMARY KEY LocationID
       SOURCE(HTTP(URL 'https://datasets-documentation.s3.eu-west-3.amazonaws.com/nyc-taxi/taxi_zone_lookup.csv' FORMAT 'CSVWithNames'))
       LIFETIME(MIN 0 MAX 0)
       LAYOUT(HASHED_ARRAY())
   $$, 'host=localhost dbname=taxi');
   ```

<Note>
  Définir `LIFETIME` sur 0 désactive les mises à jour automatiques afin d'éviter un
  trafic inutile vers notre bucket S3. Dans d'autres cas, vous pourriez le configurer
  autrement. Pour plus de détails, consultez [Actualisation des données du dictionnaire avec
  LIFETIME](/fr/reference/statements/create/dictionary/lifetime).
</Note>

2. Importez-le maintenant :

```sql theme={null}
    IMPORT FOREIGN SCHEMA taxi LIMIT TO (taxi_zone_dictionary)
    FROM SERVER taxi_srv INTO taxi;
```

3. Vérifiez que nous pouvons l’interroger :

```pgsql theme={null}
    taxi=# SELECT * FROM taxi.taxi_zone_dictionary limit 3;
     LocationID |  Borough  |                     Zone                      | service_zone
    ------------+-----------+-----------------------------------------------+--------------
             77 | Brooklyn  | East New York/Pennsylvania Avenue             | Boro Zone
            106 | Brooklyn  | Gowanus                                       | Boro Zone
            103 | Manhattan | Governor's Island/Ellis Island/Liberty Island | Yellow Zone
    (3 rows)
```

4. Excellent. Utilisez maintenant la fonction `dictGet` pour récupérer le
   nom d’un borough dans une requête. Cette requête additionne le nombre de trajets
   en taxi par borough qui se terminent à l’aéroport de LaGuardia ou à JFK :

```pgsql theme={null}
    taxi=# SELECT
            count(1) AS total,
            COALESCE(NULLIF(dictGet(
                'taxi.taxi_zone_dictionary', 'Borough',
                toUInt64(pickup_nyct2010_gid)
            ), ''), 'Unknown') AS borough_name
        FROM taxi.trips
        WHERE dropoff_nyct2010_gid = 132 OR dropoff_nyct2010_gid = 138
        GROUP BY borough_name
        ORDER BY total DESC;
     total | borough_name
    -------+---------------
     23683 | Unknown
      7053 | Manhattan
      6828 | Brooklyn
      4458 | Queens
      2670 | Bronx
       554 | Staten Island
        53 | EWR
    (7 rows)

    Time: 66.245 ms
```

Cette requête calcule le nombre de trajets en taxi par borough qui se terminent soit
à l’aéroport de LaGuardia, soit à l’aéroport JFK. Notez qu’un certain nombre de trajets ont un
quartier de prise en charge inconnu.

<div id="perform-a-join">
  ## Effectuer une jointure
</div>

Rédigez quelques requêtes qui effectuent une jointure entre `taxi_zone_dictionary` et votre
table `trips`.

1. Commencez par un `JOIN` simple, similaire à la requête précédente sur l’aéroport
   ci-dessus :

   ```pgsql theme={null}
   taxi=# SELECT
       count(1) AS total,
       "Borough"
   FROM taxi.trips
   JOIN taxi.taxi_zone_dictionary
     ON trips.pickup_nyct2010_gid = toUInt64(taxi.taxi_zone_dictionary."LocationID")
   WHERE pickup_nyct2010_gid > 0
     AND dropoff_nyct2010_gid IN (132, 138)
   GROUP BY "Borough"
   ORDER BY total DESC;
    total | borough_name
   -------+---------------
     7053 | Manhattan
     6828 | Brooklyn
     4458 | Queens
     2670 | Bronx
      554 | Staten Island
       53 | EWR
   (6 rows)

   Time: 48.449 ms
   ```

<Note>
  Notez que le résultat de la requête `JOIN` ci-dessus est identique à celui de la
  requête `dictGet` ci-dessus (à l’exception des valeurs `Unknown`, qui ne sont pas incluses). En coulisses,
  ClickHouse appelle en réalité la fonction `dictGet` pour
  le dictionnaire `taxi_zone_dictionary`, mais la syntaxe `JOIN` est plus
  familière pour les développeurs SQL.
</Note>

```pgsql theme={null}
    taxi=# explain SELECT
            count(1) AS total,
            "Borough"
        FROM taxi.trips
        JOIN taxi.taxi_zone_dictionary
          ON trips.pickup_nyct2010_gid = toUInt64(taxi.taxi_zone_dictionary."LocationID")
        WHERE pickup_nyct2010_gid > 0
          AND dropoff_nyct2010_gid IN (132, 138)
        GROUP BY "Borough"
        ORDER BY total DESC;
                                  QUERY PLAN
    -----------------------------------------------------------------------
     Foreign Scan  (cost=1.00..5.10 rows=1000 width=40)
       Relations: Aggregate on ((trips) INNER JOIN (taxi_zone_dictionary))
    (2 rows)
    Time: 2.012 ms
```

2. Cette requête renvoie les lignes correspondant aux 1000 trajets avec le montant de
   pourboire le plus élevé, puis associe chaque ligne au dictionnaire via une jointure interne :

   ```sql theme={null}
   taxi=# SELECT *
   FROM taxi.trips
   JOIN taxi.taxi_zone_dictionary
       ON trips.dropoff_nyct2010_gid = taxi.taxi_zone_dictionary."LocationID"
   WHERE tip_amount > 0
   ORDER BY tip_amount DESC
   LIMIT 1000;
   ```

<Note>
  En règle générale, nous évitons d'utiliser `SELECT *` dans PostgreSQL et ClickHouse. Vous
  ne devez récupérer que les colonnes dont vous avez réellement besoin.
</Note>

[ClickHouse tutorial]: /get-started/quickstarts/tutorial "Tutoriel ClickHouse avancé"

[psql]: https://www.postgresql.org/docs/current/app-psql.html "Applications clientes PostgreSQL : psql"

[EXPLAIN]: https://www.postgresql.org/docs/current/sql-explain.html "Commandes SQL : EXPLAIN"

[dictionary]: /reference/statements/create/dictionary

[PGXN]: https://pgxn.org/dist/pg_clickhouse "pg_clickhouse sur PGXN"

[GitHub]: https://github.com/ClickHouse/pg_clickhouse/releases "Versions de pg_clickhouse sur GitHub"

[pg_clickhouse image]: https://github.com/ClickHouse/pg_clickhouse/pkgs/container/pg_clickhouse "Image OCI pg_clickhouse sur GitHub"

[Postgres image]: https://hub.docker.com/_/postgres "Image OCI Postgres sur Docker Hub"

[Refreshing dictionary data using LIFETIME]: /reference/statements/create/dictionary/lifetime "Documentation ClickHouse : actualisation des données du dictionnaire avec LIFETIME"
