如果您是从 SQL 背景开始使用 Looker,或许会对 Looker 如何生成 SQL 感到好奇。从根本上说,Looker 是一款可生成 SQL 查询并针对数据库连接提交这些查询的工具。Looker 根据 LookML 项目(用于说明数据库中的表和列之间的关系)制定 SQL 查询。了解 Looker 如何生成查询,有助于您更好地了解 LookML 代码如何转换为高效的 SQL 查询。
每个 LookML 参数都会通过更改查询的结构、内容或行为,控制 Looker 如何生成 SQL 的某一方面。本页介绍了有关 Looker 如何生成 SQL 的原则,但并未详细介绍所有 LookML 元素。如需查看有关 LookML 参数的信息,不妨先从 LookML 快速参考文档页面着手。
查看查询
在保存的 Look 或探索中,您可以使用 Data 部分中的 SQL 标签页查看 Looker 发送到数据库以获取数据。您还可以使用底部的链接在 SQL Runner 中查看查询,或查看数据库的查询查询计划。如需详细了解 SQL Runner,请参阅 SQL Runner 基础知识文档页面。如需详细了解如何使用 SQL Runner 优化查询,请参阅如何使用 EXPLAIN 优化 SQL 社区帖子。
Looker 的规范形式
Looker 的 SQL 查询始终采用以下形式。
SELECT
<dimension>, <dimension>, ...
<measure>, <measure>, ...
FROM <explore>
LEFT JOIN <view> ON ...
LEFT JOIN <view> ON ...
WHERE (<dimension_filter_expression>) AND (<dimension_filter_expression>) AND ...
GROUP BY <dimension>, <dimension>, <dimension>, ...
HAVING <measure_filter_expression> AND <measure_filter_expression> AND ...
ORDER BY <dimension> | <measure>
LIMIT <limit>
LookML 项目定义了以上公式中引用的所有维度、测量结果、探索和视图。过滤器表达式由用户在 Looker 中指定以构建临时查询。还可以直接在 LookML 中声明过滤器表达式以应用于所有查询。
Looker 查询的基本组成部分
所有 Looker 查询均由应用于 LookML 项目的这些基本参数表示,如上面的公式所示。
Looker 使用以下参数生成完整的 SQL 查询:
model
:要定位的 LookML 模型的名称,用于指定目标数据库explore
:要查询的“探索”的名称,用于填充 SQLFROM
子句- 字段:要包含在查询中的
dimension
和measure
参数,用于填充 SQLSELECT
子句 filter
:应用于零个或多个字段的 Looker 过滤条件表达式,用于填充 SQLWHERE
和HAVING
子句- 排序顺序:排序字段,以及填充 SQL
ORDER BY
子句的排序顺序。
这些参数正是用户在 Looker 探索页面上运行查询时指定的元素。在使用 Looker 执行查询的所有模式下,这些元素都会出现:在生成的 SQL 中、表示查询的网址中、Looker API 中等。
那么由 LEFT JOIN
子句指定的视图呢?JOIN
子句根据 LookML 模型的结构进行填充,LookML 模型用于指定视图如何加入探索。构建 SQL 查询时,Looker 仅在需要时包含 JOIN
子句。当用户在 Looker 中构建查询时,无需指定表的联接方式,因为这些信息是在模型中编码的,这也是 Looker 对企业用户最强大的优势之一。
示例查询和生成的 SQL
我们在 Looker 中构建了一个查询,以演示如何根据上述模式生成查询。假设某家电商商店有桌椅跟踪用户和订单。这些字段和表关系如下所示。
我们来找出按州(用户状态)分组的订单数,并按订单创建日期(ORDERS 创建日期)过滤。
Looker 探索页面中的查询结果如下。
点击 SQL 标签页会显示由 Looker 生成和执行的 SQL。
注意与上述规范公式的相似之处。Looker 的 SQL 表现出了机器生成的代码的一些特征(例如 COALESCE(users.state,'') AS "_g1"
),但始终符合公式的情况。
SELECT
<dimension>,<dimension>,...
<measure>,<measure>,...
FROM <explore>
LEFT JOIN <view> ON ...
LEFT JOIN <view> ON ...
WHERE (<dimension_filter_expression>) AND (<dimension_filter_expression>) AND ...
GROUP BY <dimension>,<dimension>,<dimension>,...
ORDER BY <dimension> | <measure>
HAVING <measure_filter_expression> AND <measure_filter_expression> AND ...
LIMIT <limit>
在 Looker 中尝试更多查询,向自己证明查询结构始终是相同的。
在 Looker 的 SQL 运行程序中运行原始 SQL
Looker 包含一个名为 SQL SQL Runner 的功能,让您可以针对在 Looker 中设置的数据库连接运行所需的任何 SQL。
由于 Looker 生成的每个查询都会生成一个功能完善的 SQL 命令,因此您可以使用 SQL Runner 来调查或使用该查询。
在 SQL Runner 中执行的原始 SQL 查询会生成相同的结果集
如果 SQL 包含任何错误,SQL Runner 将在 SQL 命令中突出显示第一个错误的位置,并在错误消息中包含错误的位置。
检查网址中的查询组件
在 Looker 中运行查询后,您可以检查扩展共享网址,以查看 Looker 查询的基本组成部分。首先,从“探索”齿轮图标中选择分享:
如果您是从 Look 开始,请点击 Look(从此处开始)的 Explore from(探索)链接,从而在“Discover”(探索)中打开查询。
随即出现共享网址窗口,其中显示展开后的网址:
网址提供了足够的信息来重新创建查询。例如,对于如下所示的共享网址:
https://<Looker instance URL>.cloud.looker.com/explore/e_thelook/events?fields=users.state,users.count
&f[users.created_year]=2020&sorts=users.count+desc&limit=500
该网址提供以下信息:
模型 | e_thelook |
探索 | events |
要查询和显示的字段 | fields=users.state,users.count |
对字段和顺序进行排序 | sorts=users.count+desc |
过滤字段和值 | f[users.created_year]=2020 |
Looker 如何构建 JOIN
请注意,在上述查询 SQL 中,orders
探索会显示在主 FROM
子句中,合并后的视图显示在 LEFT JOIN
子句中。Looker 联接的编写方式有很多种,在 LookML 中使用联接页面对此进行了更详细的说明。
SQL 块指定自定义 SQL 子句
Looker 查询的某些元素不是由机器生成的。有时,数据模型需要提供 Looker 访问底层表和计算派生值的具体细节。在 LookML 中,SQL 块是数据建模者提供的 SQL 代码段,Looker 使用它来合成完整的 SQL 表达式。
最常用的 SQL 块参数是 sql
,用于维度和测量定义。sql
参数指定用于引用底层列或执行聚合函数的 SQL 子句。通常,所有以 sql_
开头的 LookML 参数都需要某种形式的 SQL 表达式。例如:sql_always_where
、sql_on
和 sql_table_name
。如需详细了解每个参数,请参阅 LookML 参考文档。
适用于维度和指标的 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: ${cost} ;; # Specify the field that you want to average
# The field 'cost' is declared elsewhere
}
dimension: name {
sql: CONCAT(${first_name}, ' ', ${last_name}) ;;
}
dimension: days_in_inventory {
type: number
sql: DATEDIFF(${sold_date}, ${created_date}) ;;
}
如上面的最后两个维度所示,SQL 块可以使用底层数据库支持的函数(在本例中使用 MySQL 函数 CONCAT
和 DATEDIFF
)。您在 SQL 代码块中使用的代码必须与数据库使用的 SQL 方言相匹配。
派生表的 SQL 块示例
派生表还使用 SQL 代码块来指定派生表的查询。请参阅以下示例:
view: user_order_facts {
derived_table: {
sql:
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
}
}
用于过滤探索的 SQL 块示例
借助 sql_always_where
和 sql_always_having
LookML 参数,您可以通过将 SQL 块注入 SQL WHERE 或 HAVING 子句来限制可用于查询的数据。在此示例中,LookML 替换运算符 ${view_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});;
}