SQL 参数

您可以通过在原生/SQL 编辑器中向 SQL 查询添加变量来创建 SQL 模板。这些变量将创建筛选器小部件,您可以使用这些小部件来更改查询中变量的值。您还可以向问题的 URL 添加参数来设置筛选器的值,以便在问题加载时,这些值将插入到变量中。

Variables

定义变量

在您的原生查询中键入 {{variable_name}} 会创建一个名为 variable_name 的变量。

字段筛选器,一种特殊的筛选器类型,具有略有不同的语法

此示例定义了一个名为 category文本 变量


SELECT
  count(*)
FROM
  products
WHERE
  category = {{category}}

Metabase 将读取该变量并将筛选器小部件附加到查询,人们可以使用该小部件来更改插入到带引号的 cat 变量中的值。因此,如果有人在筛选器小部件中输入“Gizmo”,则 Metabase 将运行的查询将是

SELECT
  count(*)
FROM
  products
WHERE
  category = 'Gizmo'

如果您正在编写原生 MongoDB 查询,您的查询将更像这样,其中 cat 变量在 match 子句内定义。

[{ $match: { category: {{cat}} } }]

设置 SQL 变量

要将 SQL 变量设置为一个值,您可以

  • 在筛选器小部件中输入一个值,然后重新运行问题,或者
  • 向 URL 添加一个参数并加载页面。

要向 URL 添加一个值,请遵循以下语法

?variable_name=value

例如,要将问题上的 {{cat}} 变量设置为值“Gizmo”,您的 URL 看起来会像这样

https://metabase.example.com/question/42-eg-question?cat=Gizmo

要设置多个变量,请用 & 符号 (&) 分隔参数

https://metabase.example.com/question/42-eg-question?cat=Gizmo&maxprice=50

SQL 变量类型

当您定义一个变量时,变量 侧面板将出现。您可以为变量设置类型,这将更改 Metabase 呈现的筛选器小部件的类型。

有四种类型的变量

  • 文本:一个纯文本输入框。
  • 数字:一个纯文本输入框。
  • 日期:一个简单的日期选择器。如果您想要更具表现力的日期选择器,例如指定范围,您将需要使用字段筛选器。
  • 字段筛选器:不同的筛选器小部件,具体取决于映射的字段。

最后一种变量类型,字段筛选器,是特殊的;它允许您创建“智能”筛选器小部件,例如搜索框、值下拉菜单或允许您指定日期范围的动态日期选择器。

您可以在查询中包含多个变量,Metabase 会向问题添加多个筛选器小部件。当您有多个筛选器小部件时,您可以单击一个筛选器小部件并拖动它来重新排列顺序。

字段筛选器变量类型

将变量设置为 字段筛选器 类型允许您将变量映射到当前数据库中任何表中的字段。字段筛选器允许您创建一个对该字段有意义的“智能”筛选器小部件。

字段筛选器变量应在 SQL 中的 WHERE 子句或 MongoDB 中的 $match 子句中使用。

字段筛选器兼容类型

字段筛选器仅适用于以下字段类型

  • 类别
  • 实体名称
  • 实体键
  • 外键
  • 城市
  • 州/省
  • 邮政编码

该字段也可以是日期或时间戳,可以在表元数据中保留为“无语义类型”。

当您将 变量类型 设置为“字段筛选器”时,Metabase 将显示一个选项,用于设置 要映射到的字段 以及 筛选器小部件类型 。筛选器小部件类型的可用选项取决于字段的类型。例如,如果您映射到“类别”类型的字段,您将看到“类别”或“无”的选项。如果您映射到“日期”字段,您将看到“无”、“月和年”、“季度和年”、“单日”、“日期范围”或“日期筛选器”的选项。

如果您没有看到显示筛选器小部件的选项,请确保映射的字段设置为上述类型之一,然后尝试从“管理面板”的“数据库”部分手动同步您的数据库,以强制 Metabase 扫描和缓存字段的值。

如果您想将字段筛选器映射到不是上面列出的兼容类型之一的字段,您需要管理员更改该列的字段类型。请参阅元数据编辑

字段筛选器语法

假设您想创建一个字段筛选器,该筛选器按州/省筛选 People 表,并且您希望人们能够一次选择多个州/省。这是查询

字段筛选器的语法与文本、数字或日期变量的语法不同。


SELECT
  *
FROM
  PEOPLE
WHERE
  {{state}}

然后,在侧面板中,选择“字段筛选器”变量类型,并选择要将变量映射到的字段(在本例中为 State)。

请注意缺少列和运算符(如 =)。您需要以这种方式构建字段筛选器的原因是处理 Metabase 为您生成代码的情况。例如,处理某人在筛选器小部件中选择多个值或日期范围的情况。使用字段筛选器,您无法控制生成的 SQL,因此如果您需要更大的控制权,则应使用一个(或多个)文本、数字或日期变量。

MongoDB 原生查询示例可能如下所示

[ {$match: {{date_var}} } ]

有关更深入的指南,请查看字段筛选器:为 SQL 问题创建智能筛选器小部件

BigQuery 和 Oracle 中的字段筛选器

确保您的 SQL 方言与您选择的数据库匹配。涉及查询中表的引用方式的常见问题

数据库 方言特点 示例
BigQuery 模式和表必须用反引号引起来。 FROM dataset.table
Oracle 模式和表必须用双引号引起来。 FROM schema.table

如需更多帮助,请参阅SQL 错误消息故障排除

如何创建不同类型的筛选器小部件

当您创建字段筛选器小部件时,Metabase 显示的筛选器小部件类型取决于 Metabase 中名为 在此字段上筛选 的字段设置。管理员可以将此字段选项设置为

  • 纯文本输入框
  • 搜索框
  • 所有值的列表(也称为下拉菜单)

日期字段将具有简单的日期筛选器(对于日期变量)或动态日期选择器(对于映射到日期字段的字段筛选器)。

如果您想更改特定字段的筛选器小部件,您需要请管理员在表元数据中更新该字段并设置所需的“在此字段上筛选”选项。

带有纯文本输入框的筛选器小部件

创建一个简单的 文本 数字 变量。此外,您可以将字段筛选器与 在此字段上筛选 值设置为“纯文本输入框”的字段一起使用。

注意:为防止 SQL 注入攻击,Metabase 会将搜索框中的任何内容转换为字符串。如果您想使用通配符,请查看我们的学习文章

  • 在您的查询中包含一个 SQL 变量。
  • 变量类型 设置为 字段筛选器
  • 要映射到的字段 设置为类型为“类别”的字段,该字段的 在此字段上筛选 选项设置为“搜索框”

要创建带有搜索和所有值列表的下拉菜单,您需要

  • 在您的查询中包含一个 SQL 变量。
  • 变量类型 设置为 字段筛选器
  • 要映射到的字段 设置为类型为“类别”的字段,该字段的 在此字段上筛选 选项设置为“所有值的列表”。
  • 筛选器小部件类型 设置为“类别”。

如果您要为其创建下拉菜单的字段未设置为类型“类别”,并且 在此字段上筛选 设置为“所有值的列表”,则管理员需要更新该字段的设置。例如,如果您想为不兼容的字段类型(如电子邮件字段)创建下拉菜单,则管理员需要将该字段类型更改为“类别”,将 在此字段上筛选 选项设置为 所有值的列表 ,然后重新扫描该字段的值。

但是,如果该列中有太多不同的值无法在下拉菜单中显示,Metabase 将仅显示搜索框。因此,如果您有很多电子邮件地址,您可能仍然只会得到一个搜索框。当只有少量值可供选择时(例如美国五十个州),下拉菜单小部件效果更好。

字段筛选器限制

在尝试设置字段筛选器变量时,可能会让您感到困惑的一些事项。

字段筛选器不适用于表别名

您将无法从在连接或 CTE 的表别名查询中使用字段筛选器中选择值。

原因是字段筛选器根据映射的字段生成 SQL;Metabase 不解析 SQL,因此它无法判断别名指的是什么。您有三种解决方法选项,具体取决于查询的复杂程度。

  1. 使用完整的表名。
  2. 将 CTE 替换为子查询。
  3. 在您的数据库中创建一个视图,并将该视图用作查询的基础。

字段筛选器必须连接到查询中包含的字段

您的主查询应知道您的字段筛选器变量指向的所有表,否则您将收到 SQL 语法错误。例如,假设您的主查询包含如下字段筛选器


SELECT
  *
FROM
  ORDERS
WHERE
  {{ product_category }}

假设 {{ product_category }} 变量引用了另一个使用 Products 表的问题。为了使字段筛选器工作,您需要在主查询中包含与 Products 的连接。


SELECT
  *
FROM
  ORDERS
  JOIN PRODUCTS ON ORDERS.product_id = PRODUCTS.id
WHERE
  {{ product_category }}

自定义下拉列表和搜索框值

使用文本和字段筛选器变量,您可以告诉 Metabase 人们在使用带有下拉列表或搜索框的筛选器时可以从哪些值中选择。

  1. 在原生编辑器中,在双大括号中添加 {{variable}}。
  2. 如果侧边栏未打开,您可以单击右侧的 {x} 图标以打开 变量 侧边栏。
  3. 设置 选项卡中,将 变量类型 设置为“文本”或“字段筛选器”。
  4. 在侧边栏中,转到 用户应如何筛选此变量? 选择 下拉列表 搜索框
  5. 在您选择的选项旁边,单击 编辑
  6. Metabase 将弹出一个模态框,您可以在其中选择 值应来自何处

您可以选择

  • 来自连接的字段 如果您选择了字段筛选器变量类型,您还可以选择使用连接的字段。
  • 来自另一个模型或问题。如果您选择此选项,您需要选择一个模型或问题,然后从该模型或问题中选择一个字段,Metabase 将使用该字段来提供该下拉菜单或搜索框的值。例如,如果您希望下拉菜单列出帐户可能使用的不同计划,您可以选择您创建的“帐户”模型,然后选择“计划”字段来驱动该下拉菜单。然后,下拉菜单将列出“帐户”模型中“计划”列中出现的所有不同计划选项。
  • 自定义列表。在每行上输入一个项目。您可以输入任何您喜欢的字符串值。

您还可以更改仪表盘筛选器的可选值

在筛选器小部件中设置默认值

在变量侧边栏中,您可以为变量设置默认值。默认情况下,此值将插入到相应的筛选器小部件中(即使筛选器小部件为空)。您需要在筛选器小部件中插入一个新值才能覆盖默认值。

在查询中设置复杂的默认值

您还可以通过将注释语法括在可选参数的结束括号内来直接在查询中定义默认值。

WHERE column = [[ {{ your_parameter }} --]] your_default_value

当您向 your_parameter 传递值时,注释将“激活”。

当您定义复杂的默认值时,这非常有用(例如,如果您的默认值是一个函数,如 CURRENT_DATE)。以下是一个 PostgreSQL 示例,它使用 CURRENT_DATE 将日期过滤器的默认值设置为当前日期


SELECT
  *
FROM
  orders
WHERE
  DATE(created_at) = [[ {{dateOfCreation}} --]] CURRENT_DATE

如果您向变量传递一个值,WHERE 子句将运行,包括注释语法,该语法会注释掉默认的 CURRENT_DATE 函数。

请注意,用于注释文本的井号 (--) 可能需要替换为您正在使用的数据库特定的注释语法。

为过滤器小部件要求值

变量设置侧边栏中,您可以切换始终需要一个值选项。如果您启用此选项

  • 您必须输入一个默认值。
  • 默认值将覆盖代码中的任何可选语法(例如可选的 WHERE 子句)。如果未向过滤器传递任何值,Metabase 将使用默认值运行查询。单击编辑器中的眼睛图标以预览 Metabase 将运行的 SQL。

使变量成为可选

您可以在查询中使子句成为可选。例如,您可以创建一个包含 SQL 变量的可选 WHERE 子句,这样,如果没有为变量提供值(无论是在过滤器中还是通过 URL),查询仍然会像没有 WHERE 子句一样运行。

要在您的原生查询中使变量成为可选,请将包含 {{variable}} 的整个子句放在 [[ .. ]] 方括号中。如果有人在过滤器小部件中为 variable 输入一个值,Metabase 会将该子句放在模板中;否则,Metabase 将忽略该子句并运行查询,就像该子句不存在一样。

在此示例中,如果没有为 cat 提供值,则查询将仅从 products 表中选择所有行。但是,如果 cat 有一个值,例如“Widget”,则查询将仅获取类别类型为 Widget 的产品


SELECT
  count(*)
FROM
  products
[[WHERE category = {{cat}}]]

您的 SQL 也必须能够在没有 [[ ]] 中的可选子句的情况下运行

您需要确保在没有为括号子句中的变量传递值时,您的 SQL 仍然有效。

例如,如果未为 cat 提供值,则从括号子句中排除 WHERE 关键字将导致错误

-- this will cause an error:

SELECT
  count(*)
FROM
  products
WHERE
  [[category = {{cat}}]]

这是因为当没有为 cat 提供值时,Metabase 将尝试执行 SQL,就像 [[ ]] 中的子句不存在一样

SELECT
  count(*)
FROM
  products
WHERE

这不是有效的 SQL 查询。

相反,将整个 WHERE 子句放在 [[ ]]


SELECT
  count(*)
FROM
  products
[[WHERE
  category = {{cat}}]]

当没有为 cat 提供值时,Metabase 将只执行


SELECT
  count(*)
FROM
  products

这仍然是一个有效的查询。

当使用多个可选子句时,您至少需要一个 WHERE

要使用多个可选子句,您必须至少包含一个常规的 WHERE 子句,后跟可选子句,每个子句都以 AND 开头


SELECT
  count(*)
FROM
  products
WHERE
  TRUE
  [[AND id = {{id}}]
  [[AND {{category}}]]

最后一个子句使用字段过滤器(请注意 AND 子句中缺少列)。当使用字段过滤器时,您必须在查询中排除列;您需要在侧面板中映射变量。

MongoDB 中的可选变量

如果您正在使用 MongoDB,您可以像这样使子句成为可选


[
    [[{
        $match: {category: {{cat}}}
    },]]
    {
        $count: "Total"
    }
]

或使用多个可选过滤器


[
    [[{ $match: {{cat}} },]]
    [[{ $match: { price: { "$gt": {{minprice}} } } },]]
    {
        $count: "Total"
    }
]

将 SQL 问题连接到仪表板过滤器

为了使保存的 SQL/原生问题可与仪表板过滤器一起使用,该问题必须至少包含一个变量。

可与 SQL 问题一起使用的仪表板过滤器类型取决于字段。例如,如果您有一个名为 {{var}} 的字段过滤器,并且您将其映射到“州”字段,您可以将“位置”仪表板过滤器映射到您的 SQL 问题。在此示例中,您将创建一个新的仪表板(或转到现有的仪表板),单击铅笔图标进入仪表板编辑模式,添加包含您的“州”字段过滤器变量的 SQL 问题,添加一个新的仪表板过滤器(或编辑现有的“位置”过滤器),然后单击 SQL 问题卡上的下拉菜单以查看“州”字段过滤器。

如果您向问题添加日期变量,那么只能使用仪表板过滤器选项单个日期。因此,如果您尝试在仪表板上使用其他时间选项之一,则需要将变量更改为 字段过滤器 变量并将其映射到日期列。

Field filter

有关 仪表板过滤器 的更多信息。

进一步阅读

阅读其他 Metabase 版本 的文档。