sql-style-guide

SQL Style Guide

Ce guide établit nos standards pour le SQL et est appliqué par le linter SQLFluff et par la revue de code. Les modifications du code cible auxquelles ce guide de style s’applique sont celles effectuées à l’aide de dbt.

Si vous ne faites pas partie de l’équipe Data ou si vous développez du SQL en dehors de dbt, gardez à l’esprit que les outils de linting peuvent être plus difficiles à appliquer, mais vous êtes invités à suivre les conseils donnés dans ce guide.

Utilisation

Nous nous attendons à ce que les gens utilisent les règles présentées dans ce guide pendant leur développement.

La mise en application est encore attendue car il n’y a pas de contrôle automatique effectué lors du merge dans le dépôt GitHub.

Plus tard, un contrôle automatique sera exécuté avec chaque changement et sera éventuellement rendu obligatoire pour que le merge passe.

L’intention est que les modèles soient mis à jour dans le nouveau style au fur et à mesure qu’ils sont travaillés, car toutes les règles ne peuvent pas être appliquées automatiquement (comme l’aliasing explicite des colonnes).

Le but est de les mettre à jour au fur et à mesure des interventions à venir sur ces modèles.

SQLFluff

SQLFLuff est un linter SQL qui fonctionne avec des outils de modélisation comme dbt.

Nous l’utilisons pour définir la structure et le style de base du SQL que nous écrivons et pour confier la révision de cette structure et de ce style aux autres contributrices et contributeur(s) du projet.

SQLFluff est inclus dans l’environnement de développement dbt et utilise le moteur de modélisation dbt pendant le processus de linting. Il peut être utilisé avec la commande suivante:

$ sqlfluff lint models/path/to/file/file-to-lint.sql

Une commande dbt peut également être utilisée pour obtenir la liste de fichiers à lint:

$ sqlfluff lint $(dbt list --model model_name --output path)

Si vous écrivez du SQL qui n’est pas modélisé à l’aide de dbt, vous pouvez installer et utiliser SQLFluff directement car il s’agit d’un paquet python autonome.

$ pip install sqlfluff
$ sqlfluff lint path/to/file/file-to-lint.sql

SQLFluff inclut une commande fix qui appliquera des corrections aux violations de règles quand cela est possible.

Toutes les violations de règles ne peuvent pas être corrigées automatiquement; par conséquent, nous vous encourageons à exécuter la commande lint après avoir utilisé la commande fix pour vous assurer que toutes les violations de règles ont été résolues.

Quelques Conseils

Bonnes Pratiques

Commentaires

Commentaire SQL = “comment”, Documentation dbt = “quoi, pourquoi, pour qui”

Conventions de nommage

Conventions en cas de référence

Common Table Expressions (CTEs)

Types de Données

L’exception à cette règle concerne les timestamps. Préférez TIMESTAMP à TIME. Notez que la valeur par défaut de TIMESTAMP est TIMESTAMP_NTZ qui n’inclut pas de fuseau horaire.

Fonctions

De manière générale, tout ce qui réduit le temps de cerveau disponible est recommandé.

Code d’exemple

Cet exemple de code a été traité par SQLFluff linter et le guide de style a été appliqué.


WITH my_data AS (

  SELECT *
  FROM prod.my_data
  WHERE filter = 'my_filter'

),

some_cte AS (

  SELECT DISTINCT
    id AS other_id,
    other_field_1,
    other_field_2,
    date_field_at,
    data_by_row,
    field_4,
    field_5,
    LAG(
      other_field_2
    ) OVER (PARTITION BY other_id, other_field_1 ORDER BY 5) AS previous_other_field_2
  FROM prod.my_other_data

),
/*
Il s'agit d'un commentaire très long : C'est une bonne pratique de laisser des commentaires dans le code pour code pour expliquer la logique complexe des CTE ou la logique métier qui peut ne pas être quelqu'un qui n'a pas une connaissance approfondie de la source de données. Cela peut aider les nouveaux utilisateurs à se familiariser rapidement avec le code.
*/

final AS (

  SELECT
    -- Il s'agit d'un commentaire mono-ligne
    my_data.field_1 AS detailed_field_1,
    my_data.field_2 AS detailed_field_2,
    my_data.detailed_field_3,
    DATE_TRUNC('month', some_cte.date_field_at) AS date_field_month,
    some_cte.data_by_row['id']::NUMBER AS id_field,
    IFF(my_data.detailed_field_3 > my_data.field_2, TRUE, FALSE) AS is_boolian,
    CASE
      WHEN
        my_data.cancellation_date IS NULL
        AND my_data.expiration_date IS NOT NULL
        THEN my_data.expiration_date
      WHEN my_data.cancellation_date IS NULL
        THEN my_data.start_date + 7 -- There is a reason for this number
      ELSE my_data.cancellation_date
    END AS adjusted_cancellation_date,
    SUM(some_cte.field_4) AS field_4_sum,
    MAX(some_cte.field_5) AS field_5_max
  FROM my_data
  LEFT JOIN some_cte
    ON my_data.id = some_cte.id
  WHERE my_data.field_1 = 'abc'
    AND (my_data.field_2 = 'def' OR my_data.field_2 = 'ghi')
  GROUP BY 1, 2, 3, 4, 5, 6
  HAVING COUNT(*) > 1
  ORDER BY 8 DESC
)

SELECT *
FROM final

Autres Guides populaires