SQL 问题的字段过滤器
了解如何在 SQL 查询中使用 Metabase 字段过滤器来构建更智能的过滤器小部件。
本文展示了如何使用一种称为字段过滤器的特殊变量类型,向 Metabase 中的 SQL 查询添加智能 SQL 过滤器小部件。
字段过滤器简介
对于用 SQL 编写的 Metabase 问题,我们可以使用基本变量类型——文本、数字和日期——来创建简单的 SQL 过滤器小部件。为了创建“更智能”的过滤器小部件,这些小部件可以显示特定于已过滤列中数据的选项(例如,创建值下拉菜单),我们可以使用一种称为字段过滤器的特殊变量类型。
字段过滤器最初可能会让某些人感到困惑,因为它们仅适用于某些字段,并且人们希望它们像基本输入变量一样运行(但事实并非如此)。但是,字段过滤器非常值得学习,因为您可以使用它们创建更复杂的过滤器小部件。本文将深入探讨字段过滤器,但首先让我们讨论字段过滤器变量与基本文本、数字和日期变量之间的主要区别。
区分字段过滤器与简单的文本、数字和日期变量
- 字段过滤器默认是可选的。 如果未提供值,则 SQL 查询将像字段过滤器不存在一样运行。但是,您可以选择要求提供值。
- 字段过滤器不适用于表别名。 由于字段过滤器依赖于有关表中列(以及这些表的特定名称)的元数据,因此过滤器无法“知道”您已为表设置别名。并且根据您使用的数据库,您可能需要在
FROM
子句中包含完整的架构路径。 - 字段过滤器使用特殊的语法,以便它们可以在幕后处理 SQL 代码。 您只需向
WHERE
子句提供字段过滤器(没有列或运算符),字段过滤器将为您管理 SQL 代码。这允许代码考虑人们在过滤器小部件中所做的多项选择。
第 3 点可能特别令人困惑,因此让我们用一个示例来解释它。
创建带有下拉菜单的 SQL 过滤器小部件
我们将使用 Metabase 附带的示例数据库,向用 SQL 编写的问题添加带有下拉菜单的过滤器小部件。假设我们要创建一个 SQL 问题,该问题从 Orders
表中获取所有订单,但我们希望让人们可以选择按 Products
表中的类别筛选结果。我们可以使用基本输入变量创建一个 Products.category
过滤器,如下所示
SELECT *
FROM Orders
LEFT JOIN Products
ON Orders.product_id = Products.id
[[WHERE Products.category = {{category}}]];
在这种情况下,我们将 WHERE
子句用双括号括起来以使输入成为可选,并使用变量侧边栏将变量类型设置为 Text
,并将过滤器小部件标签设置为 Category
。这种方法可行,但并不理想
- 为了筛选数据,人们必须知道哪些类别存在(并在输入时正确拼写它们)。
- 此外,他们一次无法选择多个类别,因为
{{category}}
变量仅接受单个值。
相比之下,字段过滤器会将变量映射到实际的列数据。然后,连接到变量的过滤器小部件“知道”哪些类别可用,并且可以显示这些类别的下拉菜单,如下所示
关于小部件的说明:下拉菜单只是可用选项之一。对于类型为 Category
的字段,例如 Products
表中的 category
字段,我们也可以将过滤器小部件设置为搜索框或纯输入框。管理员可以在管理面板的数据模型选项卡中配置字段设置。
请注意,如果列中不同值的数量大于 300,即使您选择下拉选项,Metabase 也会自动使用搜索框。在我们的文档中了解更多关于编辑元数据的信息。
现在,让我们回到我们的问题。以下是 Products.category
字段过滤器的语法。请注意,在 WHERE
子句中,变量之前省略了列和运算符——我们将在下面详细讨论字段过滤器语法
SELECT *
FROM orders
LEFT JOIN products
ON orders.product_id = products.id
WHERE {{category}};
在 WHERE
子句中设置变量后,我们可以使用变量侧边栏将变量连接为字段过滤器。我们将设置
变量类型
为字段过滤器
。要映射到的字段
为Products → Category
。此设置告诉 Metabase 将 SQL 代码中的变量连接到Products
表的category
列。字段小部件类型
为category
。字段小部件标签
为category
。
我们不需要变量,因此不需要默认值。如果查询在过滤器小部件中没有指定值的情况下运行,则查询将返回来自所有类别的记录。
请注意,WHERE
子句未指定变量应等于哪个列。这种隐式语法(隐藏的 SQL 代码)允许字段过滤器在幕后处理 SQL 代码,以适应多项选择,例如,当用户从下拉列表中选择多个类别时。
为日期字段创建复杂的 SQL 过滤器小部件
我们可以创建一个日期类型的基本输入变量,这将添加一个带有简单日期过滤器的 SQL 过滤器小部件。相反,如果我们使用字段过滤器变量,我们可以将该变量连接到包含日期的字段(列),这将为配置过滤器小部件解锁更多选项。这是 SQL
SELECT *
FROM ORDERS
WHERE {{created_at}}
以下是映射到日期字段的字段过滤器的不同小部件类型
- 月和年
- 季度和年
- 单个日期
- 日期范围
- 相对日期
- 日期过滤器
每种小部件类型都为人们提供了不同的方式来筛选结果。以下是三个 SQL 字段过滤器示例
日期过滤器小部件类型提供了最大的灵活性,允许人们按相对日期和范围进行筛选。
字段过滤器注意事项
人们在尝试实施字段过滤器时,通常会在以下几个地方遇到困难。
字段过滤器与别名不兼容
如上所述,如果您在 SQL 查询中使用别名,则字段过滤器将不起作用。例如,此代码(带有别名)将不起作用
-- DON'T DO THIS
SELECT *
FROM orders AS o
LEFT JOIN products AS p
ON o.product_id = p.id
WHERE {{category}};
而此代码(没有别名)将起作用
SELECT *
FROM orders
LEFT JOIN products
ON orders.product_id = products.id
WHERE {{category}};
原因是字段过滤器通过分析有关您的数据的元数据(例如,表的列名)来工作,而该元数据不包括您在 SQL 代码中创建的别名。请注意,某些数据库需要在 FROM
子句中包含架构。Oracle 的一个示例是 FROM "schema"."table"
。在 BigQuery 中,需要反引号:FROM `dataset_name.table`
。
在 WHERE 子句中省略直接赋值
如上所述,围绕字段过滤器的 SQL 代码并不完全符合标准。您可能会想写
-- DON'T DO THIS
WHERE category = {{ category }}
因为这是标准 SQL 中 WHERE
子句的正确语法。但是该语法不适用于字段过滤器。字段过滤器的正确语法省略了 =
运算符
WHERE {{ category }}
此简写的原因是为了 Metabase 可以在幕后插入 SQL 代码以处理多种选择的情况,例如,当用户从下拉列表中选择多个类别时。
只有某些字段与字段过滤器兼容
这是兼容字段列表。
您可以在我们的关于字段过滤器的文档中找到不兼容的字段类型列表。
了解更多关于 SQL 过滤器和变量的信息
查看我们的基本 SQL 输入变量 - 文本、数字和日期指南。
您还可以阅读我们的文档,了解
下一步:SQL 代码段:重用和共享 SQL 代码
了解关于在 SQL 代码中使用代码段的所有知识。