整合 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} 无法与用于 datagroupssql_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_wheresql_onsql_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 函数 CONCATDATEDIFF)。

包含相关子选择的 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} 确保 created_date 字段被视为 Looker 生成的 SQL 中的日期字段,而不是转换为字符串。

您可以在引用中使用的数据类型取决于您要引用的原始字段的数据类型。例如,如果您要引用字符串字段,则唯一可以指定的数据类型是 ::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_monthgraduation_month 维度,您可以创建维度组 type: duration,计算学生入学和毕业之间相隔的月数或年数。但是,由于某些日期字段在 Looker 生成的 SQL 中转换为字符串,因此将 enrollment_monthgraduation_month 维度设置为 sql_startsql_end 的值可能会导致错误。

为避免因这些时间字段转换为字符串而引发错误,一种方法是创建 type: duration 维度组,在 sql_startsql_end 参数中引用 enrollmentgraduation 维度组中的 raw 时间范围:


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

在“探索”界面中,系统会生成一个名为注册时长的维度组,其中包含各个维度注册月数注册年数

type: duration 的维度组中使用 raw 时间范围的一种更简单替代方案是,为 sql_startsql_end 参数中引用的字段指定 ::date::datetime 引用类型。


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

此示例中的 LookML 还会创建一个“注册时长”维度组,但通过 ::date 引用,无需使用 raw 时间范围或通过 SQL 将它们转换为字符串,即可使用 enrollment_monthgraduation_month 维度。

如需查看有关如何使用 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 会在探索菜单和“探索”的标题(而非默认的用户)中显示 Okama Users

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