联接

用法


explore: explore_name {
  join: view_name { ... }
}
层次结构
join
默认值
无

接受
现有视图的名称

特殊规则
  • 此参数接受视图名称,而不是视图底层表的名称(尽管它们通常相同)
  • 如果您的方言不支持 symmetric_aggregates,则大多数测量类型都会从联接视图中排除
  • 您可以使用 from 多次联接同一视图

定义

join 可让您定义探索与视图之间的联接关系,以便合并来自多个视图的数据。对于任何给定的“探索”,您可以根据需要联接任意数量的视图。

请注意,每个视图都与数据库中的一个表或您在 Looker 中定义的派生表相关联。同样,由于“探索”与视图相关联,因此它也与某种表相关联。

与“探索”关联的表会放入 Looker 生成的 SQL 的 FROM 子句中。与联接视图关联的表会放入 Looker 生成的 SQL 的 JOIN 子句中。

主要联接参数

如需定义探索与视图之间的联接关系(SQL ON 子句),您需要将 join 与其他参数结合使用。

您必须使用 sql_on 或 foreign_key 参数来建立 SQL ON 子句。

您还需要确保使用适当的联接类型和关系,尽管 type 和 relationship 参数并非始终明确要求。如果其默认值 type: left_outer 和 relationship: many_to_one 适合您的用例,则可以排除这些参数。

这些关键参数及其与 Looker 生成的 SQL 的关系可总结如下:

  • explore 参数决定了生成的 SQL 查询的 FROM 子句中的表。
  • 每个 join 参数决定了生成的 SQL 查询的 JOIN 子句。
    • type 参数决定了 SQL 联接的类型。
    • sql_on 参数和 foreign_key 参数决定了生成的 SQL 查询的 ON 子句。

sql_on

借助 sql_on,您可以直接编写 SQL ON 子句来建立联接关系。它可以完成与 foreign_key 相同的联接,但更易于阅读和理解。

如需了解详情,请参阅 sql_on 参数文档页面。

foreign_key

foreign_key 可让您使用联接视图的主键建立联接关系,并将其与“探索”中的维度相关联。这种模式在数据库设计中非常常见,而 foreign_key 是在这些情况下表达联接的一种优雅方式。

如需全面了解,请参阅 foreign_key 参数文档页面。

type

Looker 中的大多数联接都是 LEFT JOIN,原因如本页中的尽可能不要在联接中应用业务逻辑部分所述。因此,如果您未明确添加 type,Looker 会假定您需要 LEFT JOIN。不过,如果出于某种原因,您确实需要其他类型的联接,可以使用 type 来实现。

如需查看完整说明,请参阅 type 参数文档页面。

relationship

relationship 对 Looker 生成的 SQL 没有直接影响,但对 Looker 的正常运行至关重要。如果您未明确添加 relationship,Looker 会将关系解读为 many-to-one,这意味着探索中的多行可以对应联接视图中的一行。并非所有联接都具有这种关系,具有其他关系的联接需要正确声明。

如需全面了解,请参阅 relationship 参数文档页面。

示例

将名为 customer 的视图联接到名为 order 的探索,其中联接关系为

FROM order LEFT JOIN customer ON order.customer_id = customer.id:

explore: order {
  join: customer {
    foreign_key: customer_id
    relationship: many_to_one # Could be excluded since many_to_one is the default
    type: left_outer          # Could be excluded since left_outer is the default
  }
}

将名为 address 的视图联接到名为 person 的探索,其中联接关系为

FROM person LEFT JOIN address ON person.id = address.person_id AND address.type = 'permanent':

explore: person {
  join: address {
    sql_on: ${person.id} = ${address.person_id} AND ${address.type} = 'permanent' ;;
    relationship: one_to_many
    type: left_outer # Could be excluded since left_outer is the default
  }
}

将名为 member 的视图联接到名为 event 的探索,其中联接关系为

FROM event INNER JOIN member ON member.id = event.member_id:

explore: event {
  join: member {
    sql_on: ${event.member_id} = ${member.id} ;;
    relationship: many_to_one # Could be excluded since many_to_one is the default
    type: inner
  }
}

常见挑战

join 必须使用视图名称,而不是底层表名称

join 参数仅接受视图名称,不接受与该视图关联的表名称。视图名称和表名称通常相同,这可能会导致误认为可以使用表名称。

某些类型的测量需要对称聚合

如果您不使用对称聚合,则大多数度量类型都会从联接视图中排除。为了让 Looker 在 Looker 项目中支持对称聚合,您的数据库方言也必须支持对称聚合。下表显示了在最新版本的 Looker 中,哪些方言支持对称聚合:

方言 是否支持?
Actian Avalanche
Amazon Athena
Amazon Aurora MySQL
Amazon Redshift
Amazon Redshift 2.1+
Amazon Redshift Serverless 2.1+
Apache Druid
Apache Druid 0.13.x - 0.17.x
Apache Druid 0.18+
Apache Hive 2.3+
Apache Hive 3.1.2+
Apache Spark 3+
ClickHouse
ClickHouse 26+
Cloudera Impala 3.1+
Cloudera Impala 3.1+ with Native Driver
Cloudera Impala with Native Driver
DataVirtuality
Databricks
Denodo 7
Denodo 8 & 9
Dremio
Dremio 11+
Dremio 26+ with Arrow Flight SQL
Exasol
Google BigQuery Legacy SQL
Google BigQuery Standard SQL
Google Cloud AlloyDB for PostgreSQL
Google Cloud PostgreSQL
Google Cloud SQL
Google Spanner
Greenplum
HyperSQL
IBM Netezza
MariaDB
Microsoft Azure PostgreSQL
Microsoft Azure SQL Database
Microsoft Azure Synapse Analytics
Microsoft SQL Server 2008+
Microsoft SQL Server 2012+
Microsoft SQL Server 2016
Microsoft SQL Server 2017+
MongoBI
MongoSQL
MySQL
MySQL 8.0.12+
Oracle
Oracle ADWC
PostgreSQL 9.5+
PostgreSQL pre-9.5
PrestoDB
PrestoSQL
SAP HANA
SAP HANA 2+
SingleStore
SingleStore 7+
Snowflake
Teradata
Trino
Vector
Vertica

如果没有对称聚合,非一对一的联接关系可能会在聚合函数中产生不准确的结果。由于 Looker 测量是聚合函数,因此只有 type: count(作为 COUNT DISTINCT)的测量会从联接的视图引入到探索中。如果您确实有一对一联接关系,则可以使用 relationship 参数强制包含其他测量类型,如下所示:

explore: person {
  join: dna {
    sql_on: ${person.dna_id} = ${dna.id} ;;
    relationship: one_to_one
  }
}

如需详细了解 Looker 为何采用这种方式(对于不支持对称聚合的方言),请参阅“SQL 扇出问题”社区帖子。

注意事项

您可以使用 from 多次联接同一个表

如果单个表包含不同类型的实体,则可以将一个视图多次联接到一个探索。为此,您需要使用 from 参数。假设您有一个 order 探索,需要将 person 视图联接到该探索两次:一次用于客户,一次用于客户服务代表。您可以执行如下操作:

explore: order {
  join: customer {
    from: person
    sql_on: ${order.customer_id} = ${customer.id} ;;
  }
  join: representative {
    from: person
    sql_on: ${order.representative_id} = ${representative.id} ;;
  }
}

尽可能不要在联接中应用业务逻辑

Looker 的标准联接方法是尽可能使用 LEFT JOIN。如果您发现自己正在执行类似以下的操作,请考虑采用其他方法:

explore: member_event {
  from: event
  always_join: [member]
  join: member {
    sql_on: ${member_event.member_id} = ${member.id} ;;
    type: inner
  }
}

在此示例中,我们创建了一个仅查看与已知会员相关的事件的探索。不过,在 Looker 中执行此操作的首选方法是使用 LEFT JOIN 将事件数据和成员数据组合在一起,如下所示:

explore: event {
  join: member {
    sql_on: ${event.member_id} = ${member.id} ;;
  }
}

然后,您可以创建一个维度,并将其设置为 yes 或 no(如果您只想查看会员事件),如下所示:

dimension: is_member_event {
  type: yesno
  sql: ${member.id} IS NOT NULL ;;
}

这种方法更可取,因为它让用户可以根据需要灵活地查看所有活动或仅查看会员活动。您没有强制他们通过联接仅查看成员事件。

如果不使用对称聚合,请避免使用会导致扇出的联接

本部分仅适用于不支持对称聚合的数据库方言。请参阅本页面常见挑战部分中关于对称聚合的讨论,确定您的方言是否支持对称聚合。

如果您的数据库方言不支持对称聚合,则应避免执行会导致扇出的联接。换句话说,通常应避免在探索和视图之间建立一对多关系的联接。而是应该在派生表中汇总视图中的数据,以便与探索建立一对一关系,然后将该派生表联接到探索中。

社区帖子 SQL 扇出问题中进一步解释了这一重要概念。