Vous pouvez utiliser des filtres avec modèle pour faire référence à des dates en sélectionnant les dates de début et de fin dans un filtre de date ({% date_start date_filter %}
et {% date_end date_filter %}
, respectivement). Cette page présente des exemples de cas d'utilisation et les étapes à suivre pour les réaliser.
Remarques sur la syntaxe
La syntaxe suivante fonctionne avec la plupart des dialectes, mais certains dialectes ont des cas d'utilisation spécifiques. Exemple :-
BigQuery offre un contrôle plus précis lorsque vous utilisez des fonctions de table avec caractères génériques telles que
TABLE_DATE_RANGE
etTABLE_QUERY
. Par conséquent, l'utilisation de{% table_date_range prefix date_filter %}
n'est pas suffisante pour spécifier des filtres de date. -
Hadoop permet de travailler avec des colonnes partitionnées par date, quel que soit le type (
string
,date
) ou le format (YYYY-MM-DD
) de la colonne.
Remarques sur l'utilisation
-
Lorsqu'aucune valeur n'est spécifiée pour
date_filter
,{% date_start date_filter %}
et{% date_end date_filter %}
sont tous deux évalués àNULL
. -
Dans le cas d'un
date_filter
ouvert (par exemple,before 2016-01-01
ouafter 2016-01-01
), l'un des filtres{% date_start date_filter %}
ou{% date_end date_filter %}
seraNULL
.
Pour vous assurer qu'aucun de ces deux cas ne génère de code SQL non valide, vous pouvez utiliser IFNULL
ou COALESCE
dans le code LookML.
Exemples de cas d'utilisation
Colonnes partitionnées par mois (dans BigQuery)
Dans certains ensembles de données BigQuery, les tables sont organisées par mois, et l'ID de la table comporte la combinaison année/mois en suffixe. Vous trouverez un exemple dans l'ensemble de données suivant, qui contient de nombreuses tables portant des noms tels que pagecounts_201601
, pagecounts_201602
et pagecounts_201603
.
Exemple 1: LookML qui dépend de always_filter
La table dérivée suivante utilise TABLE_QUERY([dataset], [expr])
pour obtenir l'ensemble de tables approprié à interroger:
view: pagecounts { derived_table: { sql: SELECT * FROM TABLE_QUERY([fh-bigquery:wikipedia], "length(table_id) = 17 AND table_id >= CONCAT( 'pagecounts_' , STRFTIME_UTC_USEC({% date_start date_filter %},'%Y%m') ) AND table_id <= CONCAT('pagecounts_' , STRFTIME_UTC_USEC({% date_end date_filter %},'%Y%m') )"; ) ;; } filter: date_filter { type: date } }
Remarques sur le code de l'expression:
-
table_id
fait référence au nom de la table dans l'ensemble de données. -
length(table_id) = 17
s'assure d'ignorer les autres tables portant des noms commepagecounts_201407_en_top64k
. -
STRFTIME_UTC_USEC({% date_start date_filter %},'%Y%m')
n'affichera que la partieYYYYmm
de la date de début.
Les parties date_filter
seront remplacées par NULL
. Pour contourner ce problème, vous devez ajouter un always_filter
à l'exploration:
explore: pagecounts { always_filter: { filters: [date_filter: "2 months ago"] } }
Notez que cette opération échouera toujours pour les filtres de dates antérieures à la date la plus ancienne de l'ensemble de données, car {% date_start date_filter %}
renverra NULL
.
Exemple 2: LookML qui ne dépend pas de always_filter
Vous pouvez également utiliser COALESCE
ou IFNULL
pour encoder un ensemble par défaut de tables à interroger. Dans l'exemple suivant, les deux derniers mois sont utilisés:
-
Limite inférieure:
COALESCE({% date_start date_filter %},DATE_ADD(CURRENT_TIMESTAMP(),-2,'MONTH'))
-
Limite supérieure:
COALESCE({% date_end date_filter %},CURRENT_TIMESTAMP())
view: pagecounts { derived_table: { sql: SELECT * FROM TABLE_QUERY([fh-bigquery:wikipedia], "length(table_id) = 17 AND table_id >= CONCAT( 'pagecounts_'; , STRFTIME_UTC_USEC(COALESCE({% date_start date_filter %},DATE_ADD(CURRENT_TIMESTAMP(),-2,'MONTH')),'%Y%m') ) AND table_id <= CONCAT( 'pagecounts_' , STRFTIME_UTC_USEC(COALESCE({% date_end date_filter %},CURRENT_TIMESTAMP()),'%Y%m') )" ) ;; } filter: date_filter { type: date } }
Les fichiers journaux sont exprimés en UTC lorsque vous effectuez des requêtes dans les fuseaux horaires américains (dans BigQuery)
Il arrive que vos fichiers journaux Looker soient stockés en UTC, même si vous effectuez des requêtes dans les fuseaux horaires Est ou Pacifique. Ce problème peut entraîner une situation où les fichiers journaux ont déjà été mis à jour avec la date de demain
dans le fuseau horaire local de la requête, ce qui entraîne la perte de certaines données.
La solution consiste à ajouter un jour supplémentaire à la date de fin du filtre de date pour vous assurer que ces entrées de journal sont récupérées si l'heure est passée minuit (UTC).
Les exemples suivants utilisent l'ensemble de données public [githubarchive:day]
, qui comporte une partition quotidienne des informations GitHub.
Exemple 1: LookML qui dépend de always_filter
view: githubarchive { derived_table: { sql: SELECT * FROM TABLE_DATE_RANGE([githubarchive:day.], {% date_start date_filter %}, DATE_ADD({% date_end date_filter %},1,"DAY") ) ;; } filter: date_filter { type: date } }
Étant donné que cette requête SQL échouera si NULL
est substitué aux dates, vous devez ajouter un always_filter
à l'exploration:
explore: githubarchive { always_filter: { filters: [date_filter: "2 days ago"] } }
Exemple 2: LookML qui ne dépend pas de always_filter
Dans cet exemple, la plage de dates par défaut est encodée dans LookML. Étant donné que COALESCE
renvoyait un type unknown
, j'ai finalement dû utiliser IFNULL
pour que le code SQL fonctionne.
-
Limite inférieure:
IFNULL({% date_start date_filter %},CURRENT_DATE())
-
Limite supérieure:
IFNULL({% date_end date_filter %},CURRENT_DATE())
+ 1 jour
view: githubarchive { derived_table: { sql: SELECT * FROM TABLE_DATE_RANGE([githubarchive:day.], IFNULL({% date_start date_filter %},CURRENT_TIMESTAMP()), DATE_ADD(IFNULL({% date_end date_filter %},CURRENT_TIMESTAMP()),1,"DAY") ) ;; } filter: date_filter { type: date } }
Fonctions de fenêtre des N derniers jours (dans BigQuery)
Lorsque vous effectuez certaines analyses, les calculs doivent être effectués sous une forme agrégée sur une période historique. Pour effectuer cette opération en SQL, vous devez généralement implémenter une fonction de fenêtre qui remonte jusqu'à n
lignes pour une table unique par date. Toutefois, il existe un paradoxe lorsque vous utilisez une table partitionnée par date : vous devez d'abord définir l'ensemble de tables sur lequel la requête s'exécutera, même si la requête a réellement besoin de tables historiques supplémentaires pour le calcul.
Solution:Autorisez la date de début à être antérieure aux dates fournies dans le filtre de date. Voici un exemple d'intervalle de recherche d'une semaine supplémentaire:
view: githubarchive { derived_table: { sql: SELECT y._date, y.foo, y.bar FROM ( SELECT _date, SUM(foo) OVER (ORDER BY _date RANGE BETWEEN x PRECEDING AND CURRENT ROW), COUNT(DISTINCT(bar)) OVER (ORDER BY _date RANGE BETWEEN x PRECEDING AND CURRENT ROW) FROM ( SELECT _date, foo, bar FROM TABLE_DATE_RANGE([something:something_else.], DATE_ADD(IFNULL({% date_start date_filter %},CURRENT_TIMESTAMP()), -7, "DAY"), IFNULL({% date_end date_filter %},CURRENT_TIMESTAMP())) ) x ) y WHERE {% condition date_filter %} y._date {% endcondition %};; } filter: date_filter { type: date } }
L'instruction SELECT
supplémentaire est nécessaire, car elle fournit une contrainte WHERE
pour réduire le jeu de résultats à la plage de dates spécifiée initialement par l'utilisateur dans la requête.
Table partitionnée par date via une chaîne au format AAAA-MM-JJ (dans Presto)
Dans les tables Hadoop, il est courant d'utiliser des colonnes partitionnées pour accélérer les recherches dans les colonnes fréquemment interrogées, en particulier les dates. Le format des colonnes de date peut être arbitraire, mais YYYY-MM-DD
et YYYYMMDD
sont les plus courants. Le type de la colonne de date peut être une chaîne, une date ou un nombre.
Dans cet exemple, une table Hive table_part_by_yyyy_mm_dd
comporte une colonne partitionnée dt
, une chaîne au format YYYY-MM-DD
, qui est recherchée par Presto.
Lorsque le générateur est exécuté pour la première fois, le code LookML se présente comme suit:
view: table_part_by_yyyy_mm_dd { sql_table_name: hive.taxi. table_part_by_yyyy_mm_dd ;; suggestions: no dimension: dt { type: string sql: ${TABLE}.dt ;; } }
Remarques sur le code des expressions dans les deux exemples suivants:
-
Le résultat de
date_start
etdate_end
esttype: timestamp
. -
date_format( <expr>, '%Y-%m-%d')
permet de convertir le code temporel en chaîne et au format approprié. -
coalesce
permet de gérer les valeurs NULL si un utilisateur saisit un filtre tel quebefore 2010-01-01
ouafter 2012-12-31
. -
Il s'agit d'un code de dialecte Presto. Hive présentera donc des différences dans la chaîne de format (
yyyy-MM-dd
) etdate_format
ne peut pas prendre une valeur NULL.coalesce
doit donc s'y déplacer avec une sorte de valeur par défaut.
Exemple 1: LookML qui utilise une expression de table courante pour filtrer la table
Cet exemple utilise une table dérivée pour filtrer la table.
view: table_part_by_yyyy_mm_dd { # sql_table_name: hive.taxi. table_part_by_yyyy_mm_dd suggestions: no derived_table: { sql: SELECT * FROM hive.taxi. table_part_by_yyyy_mm_dd WHERE ( coalesce( dt >= date_format({% date_start date_filter %}, '%Y-%m-%d'), TRUE) ) AND ( coalesce( dt <= date_format({% date_end date_filter %}, '%Y-%m-%d'), TRUE) ) ;; } filter: date_filter { type: date } dimension: dt { type: string sql: ${TABLE}.dt ;; } }
En règle générale, les tables partitionnées prennent trop de temps pour les analyses complètes de table (et consomment trop de ressources de cluster). Il est donc judicieux d'appliquer un filtre par défaut à l'exploration pour cette vue:
explore: table_part_by_yyyy_mm_dd { always_filter: { filters: [date_filter: "2013-01"] } }
Exemple 2: LookML qui filtre directement dans le prédicat
Cet exemple effectue le filtrage par prédicat directement sur la table, sans sous-requête ni expression de table commune.
view: table_part_by_yyyy_mm_dd { sql_table_name: hive.taxi.table_part_by_yyyy_mm_dd ;; filter: date_filter { type: date sql: ( coalesce( ${dt} >= date_format({% date_start date_filter %}, '%Y-%m-%d'), TRUE) ) AND ( coalesce( ${dt} <= date_format({% date_end date_filter %}, '%Y-%m-%'), TRUE) );; } dimension: dt { type: string sql: ${TABLE}.dt ;; } }
Nous pouvons vérifier que les partitions de table sont effectivement utilisées en vérifiant la sortie de EXPLAIN
dans SQL Runner pour une requête générée par ce LookML (vous pouvez y accéder en cliquant sur la section SQL dans l'onglet "Données" de la page "Explorer"). Vous verrez quelque chose comme ceci:
output[table_part_by_yyyy_mm_dd.count] => [count:bigint] table_part_by_yyyy_mm_dd.count := count TopN[500 by (count DESC_NULLS_LAST)] => [count:bigint] Aggregate(FINAL) => [count:bigint] count := "count"("count_4") RemoteExchange[GATHER] => count_4:bigint Aggregate(PARTIAL) => [count_4:bigint] count_4 := "count"(*) Filter[(COALESCE(("dt" >= CAST('2013-04-01' AS VARCHAR)), true) AND COALESCE(("dt" <= CAST('2016-08-01' AS VARCHAR)), true))] => [dt:varchar] TableScan[hive:hive:taxi: table_part_by_yyyy_mm_dd, originalConstraint = (COALESCE(("dt" >= CAST('2013-04-01' AS VARCHAR)), true) AND COALESCE(("dt" <= CAST('2016-08-01' AS VARCHAR)), true))] => [dt:varchar] LAYOUT: hive dt := HiveColumnHandle{clientId=hive, name=dt, hiveType=string, hiveColumnIndex=-1, partitionKey=true} :: [[2013-04-01, 2013-12-31]]
partitionKey=true
et la plage de clés de partition indiquées indiquent qu'il n'analyse que ces colonnes partitionnées.