整合 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. 视图 B 文件必须使用 include 参数添加到与视图 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 代码块示例。与 SQL 不同,LookML 替换运算符 ($) 会使这些 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 还创建了一个“Duration Enrolled”(时长已注册)维度组,但通过使用 ::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 用户,而不是默认的用户

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