完全指南:用 {{变量}} 打造可交互的原生查询模板)
Metabase SQL 参数SQL Parameters完全指南用 {{变量}} 打造可交互的原生查询模板【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabaseSQL parametersSQL 参数又称变量 variables是 Metabase 原生 SQL 编辑器中最重要的高级功能之一它允许你在 SQL 代码中插入{{variable}}占位符把一条静态查询变成可供他人填入筛选值的模板。本指南以 docs/questions/native-editor/sql-parameters.md 为核心骨架结合仓库中的姊妹文档与后端源码带你掌握变量类型、筛选控件配置、URL 传参、仪表盘过滤器联动以及 Metabase 底层完成参数替换的原理使你能在生产环境中写出可复用、可共享、防注入的 SQL 模板问题question。什么是 SQL 变量何时使用在 原生/SQL 编辑器 中你可以把变量也叫参数写进 SQL 查询从而创建SQL 模板SQL template。变量在 SQL 代码里以双花括号{{variable_name}}表示Metabase 会为每个变量自动在问题question顶部生成一个筛选控件filter widget浏览者通过控件为变量填入值后Metabase 会把它插回 SQL 再执行查询。这种机制解决的实际问题是你不需要为查看某州的数据查看某类产品的数据各写一条 SQL只需写一条带变量的通用 SQL让使用者自己选值。变量还可以连接到 仪表盘过滤器让 SQL 问题与仪表盘上的筛选器联动。使用 SQL 变量需要一定的进阶知识前置内容可先阅读 SQL 编辑器使用说明其中也提到由于 JDBC 会把单个问号?解释为参数占位符PostgreSQL 的?JSON 运算符应改用??写法。SQL 变量的类型当你定义了一个变量Metabase 会弹出Variables and parameters变量和参数侧边栏。你可以为变量设置类型类型决定了 Metabase 呈现哪种筛选控件。变量类型包括类型说明参考文档Field filter字段过滤器变量创建智能筛选控件如日期选择器、下拉菜单需要把变量连接到查询中出现的数据库字段字段过滤器Basic variables基础变量文本、数字、日期、布尔变量仅把值原样插入占位符通常在无法使用字段过滤器时才用基础 SQL 参数Time grouping时间分组参数允许使用者改变结果按日期列分组的粒度按月、周、日等时间分组参数Table variables表变量动态选择要查询哪张表与 SQL 代码片段 snippets 组合尤其好用表变量一条查询中可以包含多个变量Metabase 会在问题上添加多个控件。要调整控件的排列顺序进入编辑模式后点击任意控件并拖拽即可。字段过滤器与基础变量的语法差异字段过滤器写法WHERE {{category}}——注意不写列名和运算符不是WHERE category {{category}}。这是因为当使用者在控件里选择多个值或一个日期区间时Metabase 需要自己拼接 SQL 片段把变量整体替换成类似category IN (...)或created_at BETWEEN ? AND ?的代码因此整个条件都由变量占位。基础变量写法WHERE category {{category}}——列名、运算符由你写死Metabase 只把控件中的值原样插入占位符。例如控件中输入Gizmo实际执行的查询就是WHERE category Gizmo。基础变量还支持多选场景只要你的 SQL 能容纳多个值例如写成WHERE category IN ({{category_vars}})并把侧边栏的People can pick设置为多值即可但多选场景通常更适合改用字段过滤器。为 SQL 变量设置值给变量赋值有两种方式在筛选控件中输入值并重新运行问题在页面 URL 中附加参数后加载页面。通过 URL 设置参数URL 传参遵循如下语法?variable_namevalue例如把{{category}}变量设为GizmoURL 形如https://metabase.example.com/question/42-eg-question?categoryGizmo设置多个变量时用分隔https://metabase.example.com/question/42-eg-question?categoryGizmomaxprice50从源码角度看URL 传参属于以查询参数形式传递的 filter 值在 src/metabase/query_processor/middleware/parameters/native.clj 中values步骤会把查询参数解析成参数名 - 值的映射供后续替换阶段使用。配置筛选控件当你向 SQL 代码中添加字段过滤器或基础变量后需要在侧边栏中完成以下配置设置筛选控件类型Filter widget type可选选项取决于你使用的是字段过滤器推荐还是基础变量无法使用字段过滤器时的备选。设置控件标签Filter widget label。设置用户应如何筛选该变量How should users filter on this variable?下拉列表展示字段的全部可选值供点选搜索框允许用户输入关键字搜索特定值输入框提供一个简单的文本输入框。如果筛选器映射到了带别名的表aliased table中的字段需要填写表与字段别名。可选设置默认值Default filter widget value。关于控件的更多细节参见原生代码的筛选与参数控件。值得注意的要点字段过滤器控件的类型受管理员在表元数据中对该字段设置的Filtering on this field选项Input box / Search box / Dropdown list影响ID 类字段也支持全部三种控件。下拉/搜索框的值可以自定义来源来自连接的字段、来自另一个模型或问题还可分别指定提供值/标签的列或自定义列表。搜索框的值会被 Metabase 转成字符串以防范 SQL 注入防止把 SQL 代码塞进值里执行。侧边栏的Always require a value开关开启后必须设置默认值且默认值会覆盖代码里的可选变量语法。不同数据类型的字段过滤器可选的运算符不同文本有 String / String is not / String contains / String does not contain / String starts with / String ends with数字有 Equal to / Not equal to / Between / Greater than or equal to / Less than or equal to日期有 Month and year / Quarter and year / Single date / Date range / Relative date / All options 等。连接 SQL 问题到仪表盘过滤器要让 SQL/原生问题能配合仪表盘过滤器使用问题中必须至少包含一个变量或参数。能与 SQL 问题配合的仪表盘过滤器类型取决于该变量映射的字段。例如你有一个名为{{var}}的字段过滤器并把它映射到语义类型为State的字段就可以把位置Location仪表盘过滤器映射到该 SQL 问题。操作步骤如下新建一个仪表盘或进入已有仪表盘。点击铅笔图标进入仪表盘编辑模式。把包含State字段过滤器的 SQL 问题添加到仪表盘。添加一个新的仪表盘过滤器或编辑已有的 Location 过滤器。点击 SQL 问题卡片上的下拉菜单把控件连接到State字段过滤器。一个典型的限制是如果你在问题中添加的是基础Date变量而非字段过滤器那么仪表盘上只能使用Single Date单个日期这一种过滤器选项。因此若要在仪表盘上使用其他时间选项如日期区间、相对日期就需要把变量改成字段过滤器并映射到日期字段。进阶可选变量、时间分组与表变量围绕 SQL 参数机制还有几个高频组合技巧值得掌握均属于 SQL 参数这一主题在仓库中的扩展文档。可选变量[[...]]双括号用[[ ... ]]包住包含{{variable}}的整个子句可以让该子句可选有值时子句生效无值时整段被忽略。经典写法是把整个WHERE子句都放进双括号SELECT count(*) FROM products [[WHERE category {{cat}}]]注意必须保证去掉[[ ]]后 SQL 仍然合法。如果把WHERE关键字留在括号外无值时会产生WHERE空条件的非法 SQL。多个可选子句时需要先有一个常规WHERE子句后续每个可选子句以AND开头。也可通过[[ {{dateOfCreation}} --]]注释技巧在查询内定义复杂默认值如CURRENT_DATE。详见可选变量。时间分组参数时间分组参数允许使用者改变结果按日期列分组的粒度。它要求有一个聚合如COUNT、参数同时出现在SELECT与GROUP BY子句中SELECT COUNT(*) AS Orders, {{created_at_param}} AS Created At FROM orders GROUP BY {{created_at_param}}可以按多列分组把多个参数同时放入SELECT与GROUP BY。未设置值时Metabase 不会截断日期而会按未截断的完整日期分组可设的选项受仪表盘过滤器的时间分组参数限制。详见时间分组参数。表变量表变量让你把表名写成占位符运行时由 Metabase 用所选表的 schema 与表名替换SELECT COUNT(*) FROM {{table}}配置时把变量类型改为Table在Table to map to中选择一张表必填若想用变量名在查询其余部分引用该表则开启Emit table alias否则关闭并用自定义别名。它与 snippets 组合可做到写一次通用查询在多个问题中映射不同表。限制包括不能连接为仪表盘过滤器参数、仅原生 SQL 可用、没有输入控件、暂不支持 transforms。详见表变量。源码视角Metabase 如何解析并替换 SQL 参数理解底层实现有助于你更好地设计模板查询。Metabase 后端对原生查询参数的解析与替换逻辑集中在这几个文件src/metabase/query_processor/middleware/parameters/native.clj原生查询参数展开的入口。expand-stage会检查当前驱动是否支持:native-parameters能力支持则调用driver/substitute-native-parameters-in-stage并把展开后的:parameters与:template-tags从查询阶段中移除。src/metabase/driver/sql/parameters/substitute.cljSQL 驱动的具体替换逻辑。替换过程对每个参数对象按类型分派字段过滤器参数、时间分组参数 →substitute-field-param生成整段替换 SQL如BETWEEN ? AND ?并为?占位符补充 prepared statement 参数引用已保存问题/表的参数 →substitute-simple-query引用 snippet 的参数 →substitute-native-query-snippet还会递归解析 snippet 内部的参数无值parsed-param-no-value-placeholder的参数 → 记录为 missing位于可选子句[[...]]内的无值参数会被整体丢弃非可选的则以1 1之类的片段兜底。src/metabase/driver/sql/parameters/substitution.clj-replacement-snippet-info多方法按驱动与值的类型返回替换片段:replacement-snippet如 ?和预编译语句参数:prepared-statement-args如#t 2017-01-01。这段实现印证了文档中的几处关键行为字段过滤器必须整体替换因为多值/区间需要生成复杂片段、可选子句的裁剪规则、以及所有值都走 prepared statement 参数?占位符 独立参数值而非字符串拼接——这正是控件输入不会破坏 SQL 结构、可有效防御注入的根本原因。总结与延伸阅读SQL 参数是把 Metabase 原生 SQL 问题从一次性查询升级为可复用模板的核心能力先用{{variable}}建立占位再用侧边栏选择类型字段过滤器优先、配置控件与默认值最后通过控件、URL 参数或仪表盘过滤器三种途径为变量赋值。结合可选变量[[...]]、时间分组参数与表变量你可以构建出面向业务人员的自助式查询界面。继续深入可参考仓库内的以下文档字段过滤器为 SQL 问题创建智能筛选控件基础 SQL 参数原生代码的筛选与参数控件可选变量时间分组参数表变量仪表盘过滤器SQL 故障排查指南过滤器故障排查指南【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考