纳入 SQL 并引用 LookML 对象

若要编写强大的 LookML,您需要能够引用现有的维度、度量、视图或派生表,即使它们不在当前范围内也是如此。您还需要引用底层表中的列,并使用数据库方言的函数调用来操纵这些值。

替换运算符 ($)

替换运算符 $ 可让 LookML 代码更具可重用性和模块化,使您能够引用其他视图和派生表、SQL 表中的列或 LookML 维度和度量。这有两方面的好处。首先,您可能已经设计出一个非常复杂的维度或指标,无需再次写出所有复杂性。其次,如果您更改维度或指标的某些方面,相应更改可能会传播到依赖于该维度或指标的所有其他内容。

您可以通过多种方式使用替换运算符:

${TABLE}.column_name 引用的是与您正在处理的视图相关联的表中的列。例如:

dimension: customer_id {
  type: number
  sql: ${TABLE}.customer_id ;;
}

${field_name} 引用您正在处理的视图中的维度或度量。例如:

measure: total_population {
  type: sum
  sql: ${population} ;;
}

${view_name.field_name} 引用另一个视图中的维度或指标。例如:

dimension: lifetime_orders {
  type: number
  sql: ${user_order_facts.lifetime_orders} ;;
}

${view_name.SQL_TABLE_NAME} 引用另一个视图或派生表。请注意,此参考中的 SQL_TABLE_NAME 是一个字面值字符串,您无需将其替换为任何内容。例如:

explore: trips {
  view_label: "Long Trips"
  # This will ensure that we only see trips that are longer than average!
  sql_always_where: ${trips.trip_duration}>=(SELECT tripduration FROM ${average_trip_duration.SQL_TABLE_NAME});;
}

${view_name.SQL_TABLE_NAME} 不适用于与 datagroups 搭配使用的 sql_trigger 参数。

范围和命名

您可以为探索、视图、字段和集命名。这些 Looker 标识符不含英文引号。

LookML 字段和集具有全名和短名称:

  • 完整名称的格式为 <view>.<field-name | set-name>。左侧表示范围,即包含相应字段或集的视图。右侧指定了特定字段或集名称。
  • 简称采用 <field-name | set-name> 格式,不含分隔句点。Looker 会根据短名称的使用范围将其展开为全名。

以下示例展示了多种形式的名称和范围。这是一组不切实际的字段,但可用于演示各种可能的范围界定表达式。

view: orders {                   # "orders" becomes the containing scope
  measure: count {               # short name, equivalent to orders.count
    type: count
  }
  dimension: customer_id {       # short name, equivalent to orders.customer_id
    type: number
    sql: ${TABLE}.customer_id ;;
  }
  dimension: customer_address {  # short name, equivalent to orders.customer_address
    sql: ${customer.address} ;;  # full name, references a field defined in the "customer" view
  }
  set: drill_fields {            # short name, equivalent to orders.drill_fields
    fields: [
      count,                     # short name, equivalent to orders.count
      customer.id                # full name, references a field defined in the "customer" view
    ]
  }
}

在 dimension: customer_address 声明中,请注意 SQL 代码块 (customer) 的底层视图与封闭视图范围 (orders) 不同。当您需要比较两个不同视图之间的字段时,这会非常有用。

当某个视图(我们称之为“视图 A”)引用在另一个视图(我们称之为“视图 B”)中定义的字段时,需要注意以下几点:

  1. 必须使用 include 参数将视图 B 文件包含在与视图 A 相同的模型中。
  2. 必须在一个或多个探索中将视图 B 与视图 A 联接起来。如需了解联接,请参阅在 LookML 中使用联接页面。

SQL 方言

Looker 支持多种数据库类型,例如 MySQL、Postgres、Redshift 和 BigQuery。每个数据库支持的功能集略有不同,函数名称也各不相同,这称为 SQL 方言。

LookML 旨在与所有 SQL 方言搭配使用,并且 LookML 不会偏好任何一种方言。不过,您需要在某些 LookML 参数中添加 SQL 代码表达式(称为 SQL 块)。借助这些参数,Looker 可以将 SQL 表达式直接传递给数据库,因此您必须使用与数据库匹配的 SQL 方言。例如,如果您使用 SQL 函数,则该函数必须是您的数据库支持的函数。

SQL 代码块

某些 LookML 参数需要您提供原始 SQL 表达式,以便 Looker 了解如何从数据库中检索数据。

以 sql_ 开头的 LookML 参数需要某种形式的 SQL 表达式。例如:sql_always_where、sql_on 和 sql_table_name。SQL 代码块最常用的 LookML 参数是 sql,用于在维度和度量字段定义中指定定义维度或度量的 SQL 表达式。

您在 SQL 块中指定的代码可以只是一个字段名称,也可以是相关子选择等复杂代码。该内容可能非常复杂,几乎可以满足您在原始 SQL 中表达自定义查询逻辑的任何需求。请注意,您在 SQL 代码块中使用的代码必须与数据库使用的 SQL 方言相匹配。

维度和指标的 SQL 代码块示例

以下是维度和度量的 SQL 块示例。LookML 替换运算符 ($) 会使这些 sql 声明看起来与 SQL 非常不同。不过,在替换发生后,生成的字符串是纯 SQL,Looker 会将其注入到查询的 SELECT 子句中。

dimension: id {
  primary_key: yes
  sql: ${TABLE}.id ;;   # Specify the primary key, id
}
measure: average_cost {
  type: average
  value_format: "0.00"
  sql: ${order_items.cost} ;;   # Specify the field that you want to average
}
dimension: name {
  sql: CONCAT(${first_name}, ' ', ${last_name}) ;;
}
dimension: days_in_inventory {
  type: int
  sql: DATEDIFF(${sold_date}, ${created_date}) ;;
}

如最后两个维度所示,SQL 块可以使用底层数据库支持的函数(例如本例中的 MySQL 函数 CONCAT 和 DATEDIFF)。

包含相关子选择的 SQL 块示例

您可以在字段的 SQL 块中放置任何 SQL 语句,包括相关子选择。下面给出了一个示例:

view: customers {
  dimension: id {
    primary_key: yes
    sql: ${TABLE}.id ;;
  }
  dimension: first_order_id {
    sql: (SELECT MIN(id) FROM orders o WHERE o.customer_id=customers.id) ;;
         # correlated subselect to derive the value for "first_order_id"
  }
}

派生表的 SQL 块示例

派生表使用 SQL 块来指定派生表的查询。下面给出了一个示例:

view: user_order_facts {
  derived_table: {
    sql:            # Get the number of orders for each user
      SELECT
        user_id
        , COUNT(*) as lifetime_orders
      FROM orders
      GROUP BY 1 ;;
  }
  # later, dimension declarations reference the derived column(s)

  dimension: lifetime_orders {
    type: number
  }
}

LookML 字段类型参考

在某个字段中引用现有 LookML 字段时,您可以使用双冒号 (::) 后跟所选类型,指示 Looker 将被引用的字段视为特定数据类型。例如,如果您在其他字段中引用 orders.created_date 维度,可以使用 ${orders.created_date::date} 语法来确保 Looker 生成的 SQL 中的 created_date 字段被视为日期字段,而不是强制转换为字符串。

您可以在引用中使用的相应数据类型取决于您引用的原始字段的数据类型。例如,如果您引用的是字符串字段,则只能指定 ::string 数据类型。以下是可用于每种字段类型的允许的字段类型引用的完整列表:

  • 在对字符串字段的引用中,您可以使用 ::string。
  • 在对数字字段的引用中,您可以使用 ::string 和 ::number。
  • 在引用日期或时间字段时,您可以使用 ::string、::date 和 ::datetime。

    使用 ::string 和 ::date 的引用会返回查询时区的数据,而使用 ::datetime 的引用会返回数据库时区的数据。
  • 在引用 yesno 字段时,您可以使用 ::string、::number 和 ::boolean。

    对于不支持布尔值数据类型的数据库方言,无法使用 ::boolean 类型的字段引用。
  • 在对位置字段的引用中,您可以使用 ::latitude 和 ::longitude。

将 LookML 字段类型引用与日期字段搭配使用

举例来说,假设您有一个 enrollment_month 维度和一个 graduation_month 维度,这两个维度都是在type: time 的维度组中创建的。在此示例中,enrollment_month 维度由 type: time 的以下维度组生成:


dimension_group: enrollment {
  type: time
  timeframes: [time, date, week, month, year, raw]
  sql: ${TABLE}.enrollment_date ;;
}

同样,graduation_month 维度由以下 type: time 维度组创建:


dimension_group: graduation {
  type: time
  timeframes: [time, date, week, month, year, raw]
  sql: ${TABLE}.graduation_date ;;
}

借助 enrollment_month 和 graduation_month 维度,您可以创建 type: duration 的维度组,从而计算出学生从入学到毕业之间经过了多少个月或多少年。不过,由于 Looker 生成的 SQL 中某些日期字段被转换为字符串,因此将 enrollment_month 和 graduation_month 维度设置为 sql_start 和 sql_end 的值可能会导致错误。

为避免因将这些时间字段转换为字符串而导致错误,一种方法是创建 type: duration 的维度组,并在 sql_start 和 sql_end 参数中引用 enrollment 和 graduation 维度组中的 raw 时间范围:


dimension_group: enrolled {
  type: duration
  intervals: [month, year]
  sql_start: ${enrollment_raw} ;;
  sql_end: ${graduation_raw} ;;
}

在探索界面中,这会生成一个名为“注册时长”的维度组,其中包含“注册月数”和“注册年数”这两个单独的维度。

除了在 type: duration 的维度组中使用 raw 时段之外,还有一种更简单的替代方法,即为 sql_start 和 sql_end 参数中引用的字段指定 ::date 或 ::datetime 参考类型。


dimension_group: enrolled {
  type: duration
  intervals: [month, year]
  sql_start: ${enrollment_month::date} ;;
  sql_end: ${graduation_month::date} ;;
}

此示例中的 LookML 还创建了一个“Duration Enrolled”(注册时长)维度组,但使用 ::date 引用可让 enrollment_month 和 graduation_month 维度在不使用 raw 时间范围或通过 SQL 将其转换为字符串的情况下使用。

如需查看有关如何使用 LookML 字段类型引用来创建 type: duration 的自定义维度组的其他示例,请参阅 dimension_group 参数文档页面。

此语法不适用于 type: list 的度量,自 Looker 6.8 起,此类度量无法被引用。

LookML 常量

借助 constant 参数,您可以指定可在整个 LookML 项目中使用的常量。借助 LookML 常量,您可以定义一个值,并在项目中接受字符串的任何部分引用该值,从而减少 LookML 代码中的重复内容。

常量必须在项目清单文件中声明,并且常量的值必须是字符串。例如,您可以按如下方式定义值为 "Okayama" 的常量 city:

constant: city {
  value: "Okayama"
}

然后,您可以使用 @{city} 语法在整个项目中引用 city 常量。例如,您可以在 users 探索中使用 city 常量和 label 参数:


explore: users {
  label: "@{city} Users"
}

然后,Looker 会在探索菜单和探索标题中显示 Okayama Users,而不是默认的 Users。

如需详细了解如何使用 LookML 常量编写可重用的代码,并查看相关示例,请参阅 constant 参数文档页面。