【dbt】使用dbt对表格行转列
【dbt】使用dbt对表格行转列
使用dbt
的 Jinja
语法,可以实现动态SQL的效果,拼接出想要的SQL语句。以下是关于行转列的例子,使用了Jinja
的变量、遍历语法,以及dbt
的run_query()
方法和 dbt_utils.get_column_values()
方法。
环境
- 数据库:Postgres 14
- dbt 1.5
生成测试表
- 创建源表模型
<dbt_project>/models/fct_score.sql
。
with source_data as (select 1 as id, '张三' as name, 'chinese' as class, 98 as score union all select 2 as id, '张三' as name, 'math' as class, 97 as score union all select 3 as id, '张三' as name, 'english' as class, 96 as score union all select 4 as id, '李四' as name, 'chinese' as class, 88 as score union all select 5 as id, '李四' as name, 'math' as class, 87 as score union all select 6 as id, '李四' as name, 'english' as class, 86 as score
)select * from source_data
- 执行
dbt run -s fct_score
,生成源表。
实现行转列
把 class
字段的值转成列,有三种方法,其实都是用jinja
生成需要的代码。
使用sql
把class
字段的值转成列,我们用常使用以下sql
。
select name,sum(case when class='chinese' then score else 0 end) as "chinese" ,sum(case when class='math' then score else 0 end) as "math" ,sum(case when class='english' then score else 0 end) as "english"
from "fct_score"
group by name
order by name
)
在dbt
中,可以利用 Jinja
语法构造出 class
课程的数组,再遍历数组的每个元素,生成 sum(...)
代码。但需要注意,最后一个sum()
语句末尾,不能带,
符号。
一、遍历数组
创建行转列的表模型 ./models/test_r2c_1.sql
。
{#1. {% set 变量名=变量值 %}: 定义数组变量 class_name_list。2. 写出基本的SQL。3. {{ for 元素名 in 数组名}}...{% endfor %}: 遍历数组, 用元素值构造出SQL。4. {% if not loop.last %}, {% endif %}: 遍历到最后一个元素时,不加逗号。
#}{% set class_name_list = ['chinese', 'math', 'english'] %}with source_data as (select name, {% for class_name in class_name_list %}sum(case when class='{{ class_name }}' then score else 0 end) as "{{ class_name }}" {% if not loop.last %}, {% endif %}{% endfor %}from {{ ref('fct_score') }}group by name order by name
)select * from source_data
运行模型dbt run -s test_r2c_1
,生成结果表。
二、使用 run_query()
方法(不推荐)
实际工作时,往往需要转换的行值很多,比如上百个行值,甚至行值是不固定的。可以使用dbt
的run_query(()
方法,先查询出字段的唯一值,再赋值给变量后进行遍历。
- 定义变量,保存查询语句。
{% set class_name_query %}select distinct class from {{ ref('fct_score') }}
{% endset %}
- 用
run_query()
方法执行查询。
{% set class_name_result = run_query(class_name_query) %}
run_query()
返回结果是对象数组, 需要取对象的第0个元素才是所需要的值。
{% set class_name_list = class_name_result.columns[0].values() %}
- 在
dbt compile
阶段,run_query()
会返回 None 值,导致报错, 所以需要把 解析run_query()
返回结果 的代码使用{% if execute %}{% endif %}
包裹, 并赋一个空数组, 以避免报错。
{% if execute %}{% set class_name_list = class_name_result.columns[0].values() %}
{% else %}{% set class_name_list=[] %}
{% endif %}
- 遍历数组, 构造SQL,代码同方法一。
- 完整代码, 保存到
./models/test_r2c_2.sql
模型中。
{% set class_name_query %}select distinct class from {{ ref('fct_score') }}
{% endset %}{% set class_name_result = run_query(class_name_query) %}{% if execute %}{% set class_name_list = class_name_result.columns[0].values() %}
{% else %}{% set class_name_list=[] %}
{% endif %}with source_data as (select name, {% for class_name in class_name_list %}sum(case when class='{{ class_name }}' then score else 0 end) as "{{ class_name }}" {% if not loop.last %}, {% endif %}{% endfor %}from {{ ref('fct_score') }}group by name order by name
)select * from source_data
- 运行模型
dbt run test_r2c_2
,获得结果如下:
注意:使用run_query()
方法时,dbt
会在本地进行编译后执行,所以如果来源字段还有上家的话,可能会导致字段值变多。
使用 dbt_utils.get_column_values()
方法(推荐)
该方法也是通过查表获得需要转换的值,但比 run_query()
方法准确,推荐使用该方法。
get_column_values()
方法需要安装dbt_utils
包,将以下内容copy
到<dbt_project>/
项目目录下的packages.yml
文件中(没有该文件就新建一个),再执行dbt deps
即可安装。
packages:- package: dbt-labs/dbt_utilsversion: 1.1.0
- 使用
get_column_values(table=ref('表名'), column='字段名')
即可查到指定字段的唯一值,并且以数组形式返回,因此使用很简单。
{% set class_name_list = dbt_utils.get_column_values(table=ref('fct_score'), column='class') %}
- 构造行转列的语句,同方法一。完整代码保存到
./models/test_r2c_3.sql
模型中。
{% set class_name_list = dbt_utils.get_column_values(table=ref('fct_score'), column='class') %}with source_data as (select name, {% for class_name in class_name_list %}sum(case when class='{{ class_name }}' then score else 0 end) as "{{ class_name }}" {% if not loop.last %}, {% endif %}{% endfor %}from {{ ref('fct_score') }}group by name order by name
)select * from source_data
- 执行
dbt run -s test_r2c_3
,得到结果如下:
【dbt】使用dbt对表格行转列相关推荐
- 表格行与列边框样式处理的原理分析及实战应用
欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:韩宇波 导语:table之间的边框存在共用问题,自然而然就存在冲突.既然存在冲突,那么就势必涉及到最后渲染哪一个样式的问题.本文就主要研 ...
- java操作跨页的word cell_Java 创建Word表格/嵌套表格、添加/复制表格行或列、设置表格跨页断行...
概述 表格作为一种可视化交流模式及组织整理数据的手段,在各种场合及文档中应用广泛.常见的表格可包含文字.图片等元素,我们操作表格时可以插入图片.写入文字及格式化表格样式等.下面,将通过Java编程在W ...
- 计算机考试行高怎么设置,2017年职称计算机考试WPS教程:表格行高列宽的调整...
2017年职称计算机考试WPS教程:表格行高列宽的调整 导语:在WPS教程中的表格行高列宽的调整是怎样的呢?下面我么一起来看看相关的具体操作是怎样的吧.更多相关内容请上应届毕业生考试网查询. 表格行高 ...
- LabVIEW 调整Table表格行高列宽的方法与例程
LabVIEW 调整Table表格行高列宽的方法与例程 在 VI 运行时,可以用两种不同的方式更改表中的列宽度.首先,可以用鼠标更改它们:其次,可以通过属性节点编程更改它们. 手部更列表的宽度 只有在 ...
- phpexcel_cell 获取表格样式_Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行...
精品推荐 国内稀缺优秀Java全栈课程-Vue+SpringBoot通讯录系统全新发布! Docker快速手上视频教程(无废话版)[免费] 作者:E-iceblue https://www.cnblo ...
- java操作跨页的word cell_Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行...
本文将对如何在Java程序中操作Word表格作进一步介绍.操作要点包括 如何在Word中创建嵌套表格. 对已有表格添加行或者列 复制已有表格中的指定行或者列 对跨页的表格可设置是否禁止跨页断行 创建表 ...
- Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行
本文将对如何在Java程序中操作Word表格作进一步介绍.操作要点包括 如何在Word中创建嵌套表格. 对已有表格添加行或者列 复制已有表格中的指定行或者列 对跨页的表格可设置是否禁止跨页断行 创建表 ...
- Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行...
点击上方 "程序员小乐"关注公众号, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 Destiny decides who enters your lif ...
- excel表格行宽列高怎么设置_excel的行高列宽怎么设置_excel的行高和列宽在哪设置...
在使用excel时,行高和列宽一定程度上影响着整个表格的美观程度,下面为你分享了几个关于行高列宽的超实用的小技巧,感兴趣的小伙伴快来看看吧! 1.行高的单位像素怎么更改为厘米? 在设置表格时,要求设置 ...
最新文章
- Hibernate 查询数据库中的数据
- HDU1753 大明A+B(大数相加)(Java题解)
- 【Windows 逆向】OD 调试器工具 ( OD 工具简介 | OD 工具与 CE 工具对比 )
- 【mysql问题】foreign key without name 解决方法
- 如何动态改变框架的大小[转]
- Dubbo 只注册,只订阅
- selenium定位输入框_[Selenium 粗浅笔记] 用Selenium填写表单
- 合肥工业大学第六届“互联网+”大学生创新创业大赛项目计划书:AI云学习 —— 一款基于Spark构建知识图谱的人工智能学习工具
- 也许你需要看看这篇文章
- domain adaptation 领域自适应
- 计算机音乐出山,《出山》音乐
- 维度诅咒_维度的诅咒减去行话的诅咒
- 一键清理系统垃圾.bat文件中的误区,你了解吗?
- 云服务器哪家好?阿里云国际版还是华为云国际版?
- 支付宝转账又出新方法:悬浮条自动识别输入,避免失误尴尬
- 5G·深·体验1:5G到底有多快?
- 【数据产品案例】阿里XSigma智能客服调度平台
- K12教育小初高各个版本教材内的章节数据
- (华硕)笔记本电脑启动提示BOOTMEG is missing
- 关闭VM中虚拟机与主机时间同步