É possível usar filtros com modelo para se referir a datas selecionando as datas de início e término em um filtro de data: {% date_start date_filter %}
e {% date_end date_filter %}
, respectivamente. Esta página guiará você por alguns exemplos de casos de uso e as etapas necessárias para realizá-los.
Observações de sintaxe
A sintaxe a seguir funciona com a maioria dos dialetos, mas alguns dialetos têm casos de uso específicos. Exemplo:-
O BigQuery permite um controle detalhado ao trabalhar com funções de caractere curinga de tabela, como
TABLE_DATE_RANGE
eTABLE_QUERY
. Portanto, usar{% table_date_range prefix date_filter %}
não é suficiente para especificar filtros de data. -
O Hadoop permite trabalhar com colunas particionadas por data, não importa o tipo (
string
,date
) ou o formato (YYYY-MM-DD
) da coluna.
Observações sobre uso
-
Quando não houver um valor especificado para
date_filter
,{% date_start date_filter %}
e{% date_end date_filter %}
serão avaliados comoNULL
. -
No caso de uma
date_filter
aberta (comobefore 2016-01-01
ouafter 2016-01-01
), um dos filtros{% date_start date_filter %}
ou{% date_end date_filter %}
seráNULL
.
Para garantir que nenhum desses dois casos resulte em SQL inválido, use IFNULL
ou COALESCE
no LookML.
Exemplos de casos de uso
Colunas particionadas mensais (no BigQuery)
Em alguns conjuntos de dados do BigQuery, as tabelas são organizadas por mês, e o ID da tabela tem a combinação ano/mês como um sufixo. Um exemplo disso é o conjunto de dados público [fh-bigquery:wikipedia]
da Wikipédia do BigQuery, que tem tabelas chamadas pagecounts_201601
, pagecounts_201602
, pagecounts_201603
e assim por diante.
Exemplo 1: LookML que depende de always_filter
A tabela derivada abaixo usa TABLE_QUERY([dataset], [expr])
para conseguir o conjunto certo de tabelas para consulta:
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 } }
Algumas observações sobre o código na expressão:
-
table_id
refere-se ao nome da tabela no conjunto de dados. -
length(table_id) = 17
garante que ignora as outras tabelas com nomes comopagecounts_201407_en_top64k
. -
STRFTIME_UTC_USEC({% date_start date_filter %},'%Y%m')
produzirá apenas a parteYYYYmm
da data de início.
NULL
será substituído pelas partes de date_filter
. Para contornar esse problema, é preciso ter um always_filter
na Análise:
explore: pagecounts { always_filter: { filters: [date_filter: "2 months ago"] } }
Observe que isso ainda falhará para filtros de datas anteriores à data mais antiga no conjunto de dados, porque {% date_start date_filter %}
será avaliado como NULL
.
Exemplo 2: LookML que não depende de always_filter
Também é possível usar COALESCE
ou IFNULL
para codificar um conjunto padrão de tabelas para consulta. No exemplo abaixo, os últimos dois meses são usados:
-
O limite inferior:
COALESCE({% date_start date_filter %},DATE_ADD(CURRENT_TIMESTAMP(),-2,'MONTH'))
-
O limite superior:
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 } }
Os arquivos de registros estão em UTC ao consultar em fusos horários dos EUA (no BigQuery)
Às vezes, os arquivos de registros do Looker são armazenados em UTC, mesmo que você esteja consultando em fusos horários do Leste ou do Pacífico. Isso pode causar um problema em que os arquivos de registro já foram lançados para a data amanhã
no fuso horário local da consulta, resultando em alguns dados perdidos.
A solução é adicionar um dia extra à data de término do filtro de data para garantir que, se passar da meia-noite UTC, essas entradas de registro serão feitas.
Os exemplos abaixo usam o conjunto de dados público [githubarchive:day]
, que tem uma partição diária de informações do GitHub.
Exemplo 1: LookML que depende 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 } }
Como esse SQL falhará se NULL
for substituído pelas datas, é necessário adicionar um always_filter
à Análise:
explore: githubarchive { always_filter: { filters: [date_filter: "2 days ago"] } }
Exemplo 2: LookML que não depende de always_filter
Neste exemplo, o período padrão é codificado no LookML. Como COALESCE
estava retornando um tipo unknown
, eu precisei usar IFNULL
para fazer o SQL funcionar.
-
O limite inferior:
IFNULL({% date_start date_filter %},CURRENT_DATE())
-
O limite superior:
IFNULL({% date_end date_filter %},CURRENT_DATE())
+ 1 dia
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 } }
Funções da janela de N dias finais (no BigQuery)
Ao realizar certas análises, os cálculos são esperados em alguma forma agregada ao longo de um período histórico. Para executar essa operação no SQL, normalmente é feita uma função de janela que retorna o número n
de linhas de uma tabela exclusiva por data. No entanto, há um catch-22 ao usar uma tabela particionada por data. É preciso primeiro ditar o conjunto de tabelas em que a consulta será executada, mesmo que a consulta realmente precise de tabelas históricas extras para computação.
A solução:permitir que a data de início seja anterior às datas fornecidas no filtro de data. Aqui está um exemplo de retorno de mais uma semana:
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 } }
A instrução SELECT
extra é necessária porque está fornecendo uma restrição WHERE
para reduzir o conjunto de resultados de volta ao período que o usuário especificou originalmente na consulta.
Tabela particionada por data via string com o formato "AAAA-MM-DD" (no Presto)
É um padrão comum nas tabelas do Hadoop usar colunas particionadas para acelerar o tempo de pesquisa de colunas que são comumente pesquisadas, especialmente datas. O formato das colunas de data pode ser arbitrário, embora YYYY-MM-DD
e YYYYMMDD
sejam os mais comuns. O tipo de coluna de data pode ser string, data ou número.
Neste exemplo, uma tabela Hive table_part_by_yyyy_mm_dd
tem uma coluna particionada dt
, uma string formatada como YYYY-MM-DD
, que está sendo pesquisada pelo Presto.
Quando o gerador é executado pela primeira vez, o LookML fica assim:
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 ;; } }
Algumas observações sobre o código nas expressões nos dois exemplos abaixo:
-
A saída de
date_start
edate_end
étype: timestamp
. -
date_format( <expr>, '%Y-%m-%d')
é usado para converter o carimbo de data/hora em uma string e no formato correto. -
O
coalesce
é para processar o caso de NULLs se alguém digitar um filtro comobefore 2010-01-01
ouafter 2012-12-31
. -
Esse é o código de dialeto Presto, de modo que o Hive terá algumas diferenças na string de formato (
yyyy-MM-dd
) edate_format
não pode assumir um valor NULL. Portanto, ocoalesce
precisaria ser movido para lá com algum tipo de valor padrão.
Exemplo 1: LookML que usa uma expressão comum para filtrar a tabela
Este exemplo usa uma tabela derivada para filtrar a tabela.
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 ;; } }
Normalmente, as tabelas particionadas levam muito tempo para fazer verificações completas de tabelas e consomem muitos recursos de cluster. Por isso, é recomendável também colocar um filtro padrão em "Explorar" para essa visualização:
explore: table_part_by_yyyy_mm_dd { always_filter: { filters: [date_filter: "2013-01"] } }
Exemplo 2: LookML que filtra diretamente no predicado
Este exemplo faz a filtragem do predicado diretamente na tabela, sem uma subconsulta ou expressão de tabela comum.
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 ;; } }
Para validar se as partições da tabela estão sendo usadas, verifique a saída de EXPLAIN
no SQL Runner para uma consulta gerada por este LookML. Para acessá-la, clique na seção SQL na guia "Dados" da página "Explorar". Você verá algo assim:
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]]
O partitionKey=true
com o intervalo de chaves de partição listado indicam que ele está verificando apenas essas colunas particionadas.