探索SQLMesh中的Jinja宏:提升SQL查询的灵活性与复用性
在数据工程和数据分析领域,SQL是不可或缺的工具。随着项目复杂度的增加,如何高效地管理和复用SQL代码成为了一个重要课题。SQLMesh作为一款强大的工具,不仅支持标准的SQL语法,还引入了Jinja模板引擎的宏功能,极大地提升了SQL查询的灵活性和复用性。本文将深入探讨SQLMesh中Jinja宏的使用方法及其优势。
什么是Jinja宏?
Jinja是一个流行的Python模板引擎,广泛用于Web开发中生成动态HTML内容。然而,Jinja的宏功能并不仅限于Web开发,它同样适用于SQL查询的构建。Jinja的宏通过字符串替换的方式工作,与SQLMesh的宏不同,它不构建语义表示,而是直接组装SQL查询文本。
Jinja的基本语法
Jinja使用大括号 {}
来区分宏和非宏文本。具体来说:
{{...}}
创建Jinja表达式,用于插入变量或函数的结果。{%...%}
创建Jinja语句,用于控制流程、设置变量等。{#...#}
创建Jinja注释,不会出现在渲染后的SQL查询中。
在SQLMesh中使用Jinja宏
为了确保SQLMesh能够正确解析包含Jinja宏的SQL查询,必须将模型查询包裹在特殊的 JINJA_QUERY_BEGIN; ...; JINJA_END;
块中。例如:
MODEL (name sqlmesh_example.full_model);
JINJA_QUERY_BEGIN;
SELECT {{ 1 + 1 }};
JINJA_END;
如果需要在模型查询之前或之后执行某些操作,可以使用 JINJA_STATEMENT_BEGIN; ...; JINJA_END;
块:
MODEL (name sqlmesh_example.full_model);
JINJA_STATEMENT_BEGIN;
{{ pre_hook() }}
JINJA_END;
JINJA_QUERY_BEGIN;
SELECT {{ 1 + 1 }};
JINJA_END;
JINJA_STATEMENT_BEGIN;
{{ post_hook() }}
JINJA_END;
SQLMesh预定义变量
SQLMesh提供了一些预定义变量,帮助用户更好地管理和构建SQL查询:
- 项目相关变量:如
runtime_stage
和this_model
,提供关于SQLMesh项目本身的信息。 - 时间相关变量:如
start_ds
和execution_date
,用于构建增量模型查询,仅在增量模型类型中可用。
使用这些变量时,需用大括号 {}
包裹变量名,并根据返回值类型决定是否加单引号。例如:
JINJA_QUERY_BEGIN;
SELECT * FROM table WHERE time_column BETWEEN '{{ start_ds }}' AND '{{ end_ds }}';
JINJA_END;
用户自定义变量
SQLMesh支持两种用户自定义宏变量:全局变量和局部变量。
全局变量
全局变量在项目配置文件中定义,可以在任何项目模型中访问。使用 var
函数获取全局变量的值,并可指定默认值以防止变量未定义的情况。例如:
JINJA_QUERY_BEGIN;
SELECT * FROM table WHERE int_variable = {{ var('int_var') }};
JINJA_END;
如果变量可能未定义,可以提供默认值:
JINJA_QUERY_BEGIN;
SELECT * FROM table WHERE some_value = {{ var('missing_var', 0) }};
JINJA_END;
局部变量
局部变量在模型定义中使用Jinja的 {% set %}
语句定义,仅在该模型中有效。例如:
MODEL (name sqlmesh_example.full_model, kind FULL, cron '@daily', audits(assert_positive_order_ids));
JINJA_QUERY_BEGIN;
{% set my_col = 'num_orders' %}
SELECT item_id, count(distinct id) AS {{ my_col }}
FROM sqlmesh_example.incremental_model
GROUP BY item_id
JINJA_END;
Jinja控制流与循环
Jinja提供了强大的控制流和循环功能,可以简化重复代码的编写。
For循环
通过 {% for %}
语句,可以轻松迭代集合中的项目。例如,创建多个条件变量:
SELECT
{% for vehicle_type in ['car', 'truck', 'bus'] %}CASE WHEN user_vehicle = '{{ vehicle_type }}' THEN 1 ELSE 0 END AS vehicle_{{ vehicle_type }},
{% endfor %}
FROM table
为了提高代码的可维护性,建议将列表定义在循环外部:
{% set vehicle_types = ['car', 'truck', 'bus'] %}
SELECT
{% for vehicle_type in vehicle_types %}CASE WHEN user_vehicle = '{{ vehicle_type }}' THEN 1 ELSE 0 END AS vehicle_{{ vehicle_type }},
{% endfor %}
FROM table
If语句
{% if %}
语句允许根据条件执行不同的操作。例如,仅在测试模式下包含特定列:
{% set testing = True %}
SELECT normal_column,
{% if testing %}testing_column
{% endif %}
FROM table
在上述例子中,如果 testing
为 True
,则渲染后的查询将包含 testing_column
。
用户自定义宏函数
Jinja宏函数允许在多个模型中复用相同的宏代码。宏函数应定义在SQLMesh项目 macros
目录下的 .sql
文件中。
定义宏函数
使用 {% macro %}
和 {% endmacro %}
语句定义宏函数。例如,定义一个简单的打印文本的宏:
{% macro print_text() %}
text
{% endmacro %}
在SQL模型中调用该宏:
{{ print_text() }}
渲染后的查询将包含 "text"
。
带参数的宏函数
宏函数可以接受参数,增强其灵活性。例如,生成带有别名的SQL列:
{% macro alias(expression, alias) %}{{ expression }} AS {{ alias }}
{% endmacro %}
在SQL查询中使用:
SELECT item_id, {{ alias('item_id', 'item_id2') }} FROM table
渲染后的查询为:
SELECT item_id, item_id AS item_id2 FROM table
需要注意的是,Jinja在渲染过程中会根据上下文识别参数类型。如果需要将表达式作为字符串处理,可以使用双引号:
SELECT item_id, {{ alias("'item_id'", 'item_id2') }} FROM table
渲染结果为:
SELECT item_id, 'item_id' AS item_id2 FROM table
最后总结
SQLMesh支持同时使用Jinja和SQLMesh的宏系统。然而,强烈建议在一个模型中仅使用一种宏系统,以避免潜在的冲突和不可预见的行为。预定义的SQLMesh宏变量可以在包含用户自定义Jinja变量和函数的查询中使用,但传递给Jinja宏函数的预定义变量必须使用Jinja的大括号语法。
通过引入Jinja宏,SQLMesh为数据工程师和分析师提供了更强大的工具来管理和复用SQL代码。无论是通过预定义变量简化动态查询的构建,还是通过自定义宏函数提升代码的复用性,Jinja宏都极大地提升了SQL查询的灵活性和可维护性。掌握这些功能,将帮助您在复杂的数据项目中更加高效地工作。
相关文章:

探索SQLMesh中的Jinja宏:提升SQL查询的灵活性与复用性
在数据工程和数据分析领域,SQL是不可或缺的工具。随着项目复杂度的增加,如何高效地管理和复用SQL代码成为了一个重要课题。SQLMesh作为一款强大的工具,不仅支持标准的SQL语法,还引入了Jinja模板引擎的宏功能,极大地提升…...
配置linux自启java程序
配置linux自启java程序 1、切换root用户,并进入自启配置目录 sudo su - cd /etc/systemd/system2、编写启动文件 例如:class-server.service vi class-server.service脚本内容 [Unit] DescriptionClassServer Java Application Afternetwork.target…...

对Redis组件的深入探讨
目录 1、磁盘和内存 1.1、概念 1.2、区别 1.3、联系 2、redis基本特性 2.1、数据结构 2.2、性能 2.3、事件驱动架构 2.4、原子性 3、redis模型 3.1、单线程 3.2、事件驱动模型 3.3、epoll多路复用 4、数据持久化 4.1、RDB快照 4.2、AOF(Append Only…...

Uni-app 组件使用
在前端开发领域,能够高效地创建跨平台应用是开发者们一直追求的目标。Uni-app 凭借其 “一次开发,多端部署” 的特性,成为了众多开发者的首选框架。而组件作为 Uni-app 开发的基础单元,合理运用组件能够极大地提升开发效率和代码的…...
k8s pod request/limit 值不带单位会发生什么?
在 Kubernetes 中,Pod 的 resources.requests 和 limits 字段必须显式指定单位。 一、未正确设置requests和limits字段的单位会产生影响? 1. 资源分配严重不足 例如,以下配置存在严重错误: resources:requests:memory: 512 # …...
Ruby 字符串(String)
Ruby 字符串(String) 引言 在编程语言中,字符串是表示文本数据的一种基本数据类型。在Ruby中,字符串处理是日常编程中非常常见的一项任务。本文将详细介绍Ruby中的字符串(String)类型,包括其创…...

嵌入式学习笔记 - STM32 SRAM控制器FSMC
一 SRAM控制器内部结构图: 以下以512K SRAM芯片为例 二 SRAM地址矩阵/寻址方式: SRAM的地址寻址方式通过行地址与列地址交互的方式存储数据 三 STM32 地址映射 从STM32的地址映射中可以看出,FSMC控制器支持扩展4块外部存储器区域࿰…...
经典算法 求解硬币组成问题
求解硬币组成问题 题目描述 实现一个算法求解组成硬币问题。介绍如下: 假设有面值给定的一些硬币,以及给定的总合值,问构成总合值的方法有多少种。 输入描述 第一行包含两个数字 N, M: N 表示硬币面值的种类数M 表示给定的总合…...

数据封装的过程
数据的封装过程 传输层 UDP 直接将数据封装为UDP数据报,添加UDP头部(8B)。 要点: UDP首部简单,无连接不可靠、无重传、无拥塞控制,适用于实时性要求较高的通讯;不需要源端口或不想计算检…...

Docker部署常见应用之Superset
文章目录 使用 Docker 部署使用 Docker Compose 部署参考文章 以下是使用 Docker 部署 Superset 并将存储配置为 MySQL 的详细步骤: 使用 Docker 部署 获取Superset镜像: 使用Docker从官方仓库拉取Superset镜像:docker pull apache/superset:4.0.0创建 …...
LeetCode 216.组合总和 III:回溯算法实现与剪枝优化
目录 问题描述解决思路 回溯法剪枝优化 代码实现复杂度分析示例测试总结与扩展 1. 问题描述 给定两个整数 k 和 n,要求找出所有满足以下条件的组合: 组合包含 k 个不同的数字。组合中数字的和等于 n。组合中的数字范围为 [1, 9],且每个数字…...

住宅 IP 地址:数字时代的真实网络身份载体
在互联网的底层架构中,IP 地址是设备连接网络的 “数字身份证”。而住宅 IP 地址作为其中最贴近真实用户的类型,特指互联网服务提供商(ISP)分配给家庭或个人用户的 IP 地址,具有以下核心特征: 物理关联性 …...
前后端开发---分离 和 不分离开发
前后端分离开发和不分离开发是两种不同的软件开发架构方式,它们的主要区别体现在以下几个方面: 对比维度 前后端分离开发 前后端不分离开发 定义 前端和后端作为两个独立项目开发,通过API接口通信 前端和后端代码混合在一起,…...

[SSM]-Spring介绍
框架是什么 框架 framework 建筑学: 用于承载一个系统必要功能的基础要素的集合计算机: 某特定领域系统的一组约定, 标准, 代码库以及工具的集合 框架vs工具 框架作为项目的骨架合基础结构, 提供了高层次的抽象和可复用性工具作为辅助手段, 帮助开发者完成特定任务并提高工作…...
Consumer Group的作用是什么?Rebalance的触发条件有哪些? (实现消费者负载均衡;消费者加入/离开、订阅Topic变化等)
好的,我现在需要回答用户关于Kafka Consumer Group和Rebalance的问题。首先,用户问的是Consumer Group的作用以及Rebalance的触发条件。根据之前的对话历史,用户已经了解了Kafka的基本组件、消息保留策略、顺序性保证等,现在的问题…...

今天的python练习题
目录 一、每日一言 二、练习题 三、效果展示 四、下次题目 五、总结 一、每日一言 晚上8点到的,还是会被感动到,有一位列车员同志在检票期间,叫我到列车员专座位上去坐,我很感激他,温暖人心,所以人间填我…...

Mysql进阶篇1_存储引擎、索引、SQL性能分析指令
文章目录 1.存储引擎InnoDBMyISAMMemory存储引擎选择和对比 2.索引索引结构索引分类索引语法索引使用(建议看完第3节后观看)!!!mysql如何使用索引查询数据(个人理解) 3.SQL性能分析SQL执行频率慢…...
02_MySQl引擎的区别
文章目录 1. InnoDB(默认引擎)2. MyISAM3. Memory4. 其他引擎核心对比总结 MySQL 存储引擎是数据库底层软件组织,不同的存储引擎提供不同的存储机制、索引技巧、锁级别和事务功能。以下是主要存储引擎的区别: 1. InnoDB࿰…...

协议(消息)生成
目录 协议(消息)生成主要做什么? 知识点二 制作功能前的准备工作 编辑编辑 制作消息生成功能 实现效果 总结 上一篇中配置的XML文件可见: https://mpbeta.csdn.net/mp_blog/creation/editor/147647176 协议(消息)生成主要做什么? //协议生成 主要是…...
SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理标准)-(一)
1 目的 物料(例如晶圆)加工在设备中的自动化管理与控制是实现工厂自动化的关键要素。本标准针对半导体制造环境中与设备内部物料处理相关的通信需求进行了规范。本标准规定了在加工单元接收到的指定材料所应适用的加工方法(例如Etch腔室需要Run哪支Recipe)。它阐述了物料加工的…...
Nginx1.26.2安装包编译安装并配置stream模块
准备nginx安装文件:nginx-1.26.2.tar.gz cd /usr/local wget http://nginx.org/download/nginx-1.26.2.tar.gz tar -zxvf nginx-1.26.2.tar.gz && cd nginx-1.26.2 1.创建安装目录 mkdir nginx 2.解压安装文件nginx-1.26.2.tar.gz tar -zxvf nginx-1.26…...

Linux 系统的指令详解介绍
Linux 系统的指令详解介绍 一、指令的本质与定义1. 什么是指令?2. Linux 指令分类二、指令格式解析1. 基础语法结构2. 语法要素详解(1)选项类型(2)参数类型三、核心指令分类1. 文件操作指令2. 文本处理指令3. 系统管理指令一、指令的本质与定义 1. 什么是指令? 定义:在…...

Milvus(17):向量索引、FLAT、IVF_FLAT
1 索引向量字段 利用存储在索引文件中的元数据,Milvus 以专门的结构组织数据,便于在搜索或查询过程中快速检索所需的信息。 Milvus 提供多种索引类型和指标,可对字段值进行排序,以实现高效的相似性搜索。下表列出了不同向量字段类…...

芯片笔记 - 手册参数注释
芯片手册参数注释 基础参数外围设备USB OTG(On-The-Go)以太网存储卡(SD)SDIO 3.0(Secure Digital Input/Output)GPIO(General Purpose Input/Output 通用输入/输出接口)ADC(Analog to Digital C…...
不同大模型对提示词和问题的符号标识
不同大模型对提示词和问题的符号标识 不同大模型对提示词和问题的符号标识存在差异,花括号{}在特定场景下可以使用,但需结合模型特性和上下文。 一、主流模型的符号标识惯例 1. Claude(Anthropic) 推荐符号:XML标签(如<tag>内容</tag>)。 示例:<text…...

RabbitMQ学习(第二天)
文章目录 1、生产者可靠性①、生产者重连②、生产者确认 2、MQ可靠性①、数据持久化②、LazyQueue(惰性队列) 3、消费者可靠性①、消费者确认②、失败重试机制③、保证业务幂等性 总结 之前的学习中,熟悉了java中搭建和操作RabbitMQ发送接收消息,熟悉使用…...

【JS逆向基础】爬虫核心模块:request模块与包的概念
前言:这篇文章主要介绍JS逆向爬虫中最常用的request模块,然后引出一系列的模块的概念,当然Python中其他比较常用的还有很多模块,正是这些模块也可以称之为库的东西构成了Python强大的生态,使其几乎可以实现任何功能。下…...

LabVIEW燃气轮机测控系统
在能源需求不断增长以及生态环境保护备受重视的背景下,微型燃气轮机凭借其在经济性、可靠性、维护性及排放性等方面的显著优势,在航空航天、分布式发电等众多领域得到广泛应用。随着计算机技术的快速发展,虚拟仪器应运而生,LabVIE…...
【链表扫盲】FROM GPT
链表是一种线性数据结构,由节点(Node)组成,每个节点包含两个部分: 数据域(data): 存储节点值。指针域(next): 存储指向下一个节点的引用。 链表…...

QT | 常用控件
前言 💓 个人主页:普通young man-CSDN博客 ⏩ 文章专栏:C_普通young man的博客-CSDN博客 ⏩ 本人giee: 普通小青年 (pu-tong-young-man) - Gitee.com 若有问题 评论区见📝 🎉欢迎大家点赞👍收藏⭐文章 —…...