„date_start“ und „date_end“ mit Datumsfiltern verwenden

Sie können Filter mit Vorlagen verwenden, um sich auf bestimmte Datumsangaben zu beziehen. Wählen Sie dazu in einem Datumsfilter das Start- und Enddatum aus ({% date_start date_filter %} bzw. {% date_end date_filter %}). Auf dieser Seite finden Sie einige Anwendungsbeispiele und die dazugehörigen Schritte.

Syntaxhinweise

Die folgende Syntax funktioniert mit den meisten Dialekten, aber bestimmte Dialekte haben spezifische Anwendungsfälle. Beispiel:

  • BigQuery bietet eine bessere Kontrolle bei der Arbeit mit Tabellen-Wildcard-Funktionen wie TABLE_DATE_RANGE und TABLE_QUERY. Daher reicht {% table_date_range prefix date_filter %} nicht aus, um Datumsfilter anzugeben.
  • In Hadoop können Sie mit datumspartitionierten Spalten arbeiten, unabhängig vom Typ (string, date) oder Format (YYYY-MM-DD) der Spalte.

Verwendungshinweise

  • Wenn für date_filter kein Wert angegeben ist, wird sowohl für {% date_start date_filter %} als auch für {% date_end date_filter %} NULL zurückgegeben.
  • Bei einer offenen date_filter (z. B. before 2016-01-01 oder after 2016-01-01) ist einer der {% date_start date_filter %}- oder {% date_end date_filter %}-Filter NULL.
  • Damit in keinem dieser beiden Fälle ungültiges SQL generiert wird, können Sie in der LookML IFNULL oder COALESCE verwenden.

Anwendungsbeispiele

Nach Monaten partitionierte Spalten (in BigQuery)

In einigen BigQuery-Datasets sind Tabellen nach Monaten organisiert und die Tabellen-ID enthält die Kombination aus Jahr und Monat als Suffix. Ein Beispiel hierfür ist der folgende Datensatz mit vielen Tabellen mit Namen wie pagecounts_201601, pagecounts_201602 und pagecounts_201603.

Beispiel 1: LookML, die von always_filter abhängt

In der folgenden abgeleiteten Tabelle wird TABLE_QUERY([dataset], [expr]) verwendet, um die richtigen Tabellen für die Abfrage abzurufen:

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
  }
}

Hinweise zum Code im Ausdruck:

  • table_id bezieht sich auf den Namen der Tabelle im Dataset.
  • length(table_id) = 17 sorgt dafür, dass die anderen Tabellen mit Namen wie pagecounts_201407_en_top64k ignoriert werden.
  • Mit STRFTIME_UTC_USEC({% date_start date_filter %},'%Y%m') wird nur der Teil YYYYmm des Startdatums ausgegeben.

NULL wird anstelle der date_filter-Teile eingefügt. Um dieses Problem zu beheben, ist ein always_filter im Explore erforderlich:

explore: pagecounts {
  always_filter: {
    filters: [date_filter: "2 months ago"]
  }
}

Bei Filtern für Datumsangaben vor dem frühesten Datum im Datenpool funktioniert das jedoch nicht, da {% date_start date_filter %} zu NULL ausgewertet wird.

Beispiel 2: LookML, die nicht von always_filter abhängt

Sie können auch COALESCE oder IFNULL verwenden, um einen Standardsatz von Tabellen zu codieren, die abgefragt werden sollen. Im folgenden Beispiel werden die letzten zwei Monate verwendet:

  • Untergrenze: COALESCE({% date_start date_filter %},DATE_ADD(CURRENT_TIMESTAMP(),-2,'MONTH'))
  • Obergrenze: 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
  }
}

Logdateien sind in UTC, wenn in BigQuery Abfragen in amerikanischen Zeitzonen ausgeführt werden

Manchmal werden Ihre Looker-Protokolldateien in UTC gespeichert, auch wenn Sie Abfragen in der Eastern- oder Pacific-Zeitzone ausführen. Dies kann dazu führen, dass die Protokolldateien in der lokalen Zeitzone der Abfrage bereits auf das Datum morgen umgestellt wurden, was zu Datenverlusten führt.

Die Lösung besteht darin, dem Enddatum des Datumsfilters einen zusätzlichen Tag hinzuzufügen, damit diese Logeinträge auch nach Mitternacht (UTC) erfasst werden.

In den folgenden Beispielen wird das öffentliche Dataset [githubarchive:day] verwendet, das eine tägliche Partition von GitHub-Informationen enthält.

Beispiel 1: LookML, die von always_filter abhängt

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
  }
}

Da diese SQL-Abfrage fehlschlägt, wenn NULL anstelle der Datumsangaben verwendet wird, muss der explorativen Datenanalyse ein always_filter hinzugefügt werden:

explore: githubarchive {
  always_filter: {
    filters: [date_filter: "2 days ago"]
  }
}

Beispiel 2: LookML, die nicht von always_filter abhängt

In diesem Beispiel ist der Standardzeitraum in der LookML codiert. Da COALESCE einen unknown-Typ zurückgab, musste ich letztendlich IFNULL verwenden, damit die SQL-Abfrage funktionierte.

  • Untergrenze: IFNULL({% date_start date_filter %},CURRENT_DATE())
  • Obergrenze: IFNULL({% date_end date_filter %},CURRENT_DATE()) + 1 Tag
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
  }
}

Funktionen für die letzten N Tage (in BigQuery)

Bei bestimmten Analysen werden Berechnungen in aggregierter Form über einen bestimmten Zeitraum erwartet. Um diesen Vorgang in SQL auszuführen, wird in der Regel eine Fensterfunktion implementiert, die n Zeilen zurückreicht, für eine Tabelle, die nach Datum eindeutig ist. Bei der Verwendung einer datumspartitionierten Tabelle gibt es jedoch eine Zwickmühle: Sie müssen zuerst die Tabellen angeben, auf die die Abfrage angewendet werden soll, auch wenn für die Berechnung zusätzliche Verlaufstabellen erforderlich sind.

Lösung:Das Startdatum darf vor den im Datumsfilter angegebenen Datumsangaben liegen. Hier ein Beispiel, das eine zusätzliche Woche zurückreicht:

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
  }
}

Die zusätzliche SELECT-Anweisung ist erforderlich, da sie eine WHERE-Einschränkung liefert, um das Ergebnis auf den ursprünglichen Zeitraum des Nutzers in der Abfrage zu begrenzen.

Tabelle, die nach Datum über einen String im Format „JJJJ-MM-TT“ (in Presto) partitioniert ist

In Hadoop-Tabellen werden häufig partitionierte Spalten verwendet, um die Suchzeiten für Spalten zu verkürzen, nach denen häufig gesucht wird, insbesondere nach Datumsangaben. Das Format der Datumsspalten kann beliebig sein, wobei YYYY-MM-DD und YYYYMMDD am häufigsten vorkommen. Der Typ der Datumsspalte kann „String“, „Datum“ oder „Zahl“ sein.

In diesem Beispiel hat eine Hive-Tabelle table_part_by_yyyy_mm_dd eine partitionierte Spalte dt, ein String im Format YYYY-MM-DD, in dem nach Presto gesucht wird.

Wenn der Generator zum ersten Mal ausgeführt wird, sieht die LookML so aus:

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 ;;
  }
}

Einige Anmerkungen zum Code in den Ausdrücken in den beiden folgenden Beispielen:

  • Die Ausgabe von date_start und date_end ist type: timestamp.
  • date_format( <expr>, '%Y-%m-%d') wird verwendet, um den Zeitstempel in einen String und in das richtige Format zu konvertieren.
  • Mit coalesce werden NULL-Werte verarbeitet, wenn ein Nutzer einen Filter wie before 2010-01-01 oder after 2012-12-31 eingibt.
  • Dies ist Presto-Dialektcode. Daher gibt es in Hive einige Unterschiede im Formatstring (yyyy-MM-dd). date_format kann keinen NULL-Wert annehmen. Daher muss coalesce mit einem Standardwert dorthin verschoben werden.

Beispiel 1: LookML mit einem gemeinsamen Tabellenausdruck zum Filtern der Tabelle

In diesem Beispiel wird eine abgeleitete Tabelle verwendet, um die Tabelle zu filtern.

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 ;;
  }
}

Normalerweise dauern vollständige Tabellenscans für partitionierte Tabellen zu lange und verbrauchen zu viele Clusterressourcen. Daher ist es empfehlenswert, auch für diese Ansicht einen Standardfilter für die explorative Datenanalyse festzulegen:

explore: table_part_by_yyyy_mm_dd {
  always_filter: {
    filters: [date_filter: "2013-01"]
  }
}

Beispiel 2: LookML, die direkt im Prädikat filtert

In diesem Beispiel wird die Prädikatsfilterung direkt auf der Tabelle ohne untergeordnete Abfrage oder gemeinsamen Tabellenausdruck durchgeführt.

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 ;;
  }
}

Wir können prüfen, ob die Tabellenpartitionen tatsächlich verwendet werden, indem wir die Ausgabe von EXPLAIN in SQL Runner für eine Abfrage prüfen, die von dieser LookML generiert wurde. Sie können darauf zugreifen, indem Sie auf dem Tab „Daten“ der Seite „Expl. Datenanalyse“ auf den Bereich „SQL“ klicken. Sie sehen dann ungefähr Folgendes:

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 und der Bereich der aufgeführten Partitionsschlüssel geben an, dass nur diese partitionierten Spalten gescannt werden.