【dbt】使用dbt对表格行转列
使用dbtJinja 语法,可以实现动态SQL的效果,拼接出想要的SQL语句。以下是关于行转列的例子,使用了Jinja的变量、遍历语法,以及dbtrun_query()方法和 dbt_utils.get_column_values() 方法。

环境

  • 数据库:Postgres 14
  • dbt 1.5

生成测试表

  1. 创建源表模型 <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
  1. 执行 dbt run -s fct_score,生成源表。

实现行转列

class 字段的值转成列,有三种方法,其实都是用jinja生成需要的代码。
使用sqlclass字段的值转成列,我们用常使用以下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() 方法(不推荐)

实际工作时,往往需要转换的行值很多,比如上百个行值,甚至行值是不固定的。可以使用dbtrun_query(()方法,先查询出字段的唯一值,再赋值给变量后进行遍历。

  1. 定义变量,保存查询语句。
{% set class_name_query %}select distinct class from {{ ref('fct_score') }}
{% endset %}
  1. run_query() 方法执行查询。
{% set class_name_result = run_query(class_name_query) %}
  1. run_query() 返回结果是对象数组, 需要取对象的第0个元素才是所需要的值。
{% set class_name_list = class_name_result.columns[0].values() %}
  1. 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 %}
  1. 遍历数组, 构造SQL,代码同方法一。
  2. 完整代码, 保存到 ./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
  1. 运行模型 dbt run test_r2c_2 ,获得结果如下:

    注意:使用 run_query() 方法时,dbt会在本地进行编译后执行,所以如果来源字段还有上家的话,可能会导致字段值变多。

使用 dbt_utils.get_column_values() 方法(推荐)

该方法也是通过查表获得需要转换的值,但比 run_query() 方法准确,推荐使用该方法。

  1. get_column_values()方法需要安装 dbt_utils 包,将以下内容 copy<dbt_project>/ 项目目录下的 packages.yml 文件中(没有该文件就新建一个),再执行 dbt deps 即可安装。
packages:- package: dbt-labs/dbt_utilsversion: 1.1.0
  1. 使用 get_column_values(table=ref('表名'), column='字段名') 即可查到指定字段的唯一值,并且以数组形式返回,因此使用很简单。
{% set class_name_list = dbt_utils.get_column_values(table=ref('fct_score'), column='class') %}
  1. 构造行转列的语句,同方法一。完整代码保存到 ./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
  1. 执行 dbt run -s test_r2c_3 ,得到结果如下:

【dbt】使用dbt对表格行转列相关推荐

  1. 表格行与列边框样式处理的原理分析及实战应用

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:韩宇波 导语:table之间的边框存在共用问题,自然而然就存在冲突.既然存在冲突,那么就势必涉及到最后渲染哪一个样式的问题.本文就主要研 ...

  2. java操作跨页的word cell_Java 创建Word表格/嵌套表格、添加/复制表格行或列、设置表格跨页断行...

    概述 表格作为一种可视化交流模式及组织整理数据的手段,在各种场合及文档中应用广泛.常见的表格可包含文字.图片等元素,我们操作表格时可以插入图片.写入文字及格式化表格样式等.下面,将通过Java编程在W ...

  3. 计算机考试行高怎么设置,2017年职称计算机考试WPS教程:表格行高列宽的调整...

    2017年职称计算机考试WPS教程:表格行高列宽的调整 导语:在WPS教程中的表格行高列宽的调整是怎样的呢?下面我么一起来看看相关的具体操作是怎样的吧.更多相关内容请上应届毕业生考试网查询. 表格行高 ...

  4. LabVIEW 调整Table表格行高列宽的方法与例程

    LabVIEW 调整Table表格行高列宽的方法与例程 在 VI 运行时,可以用两种不同的方式更改表中的列宽度.首先,可以用鼠标更改它们:其次,可以通过属性节点编程更改它们. 手部更列表的宽度 只有在 ...

  5. phpexcel_cell 获取表格样式_Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行...

    精品推荐 国内稀缺优秀Java全栈课程-Vue+SpringBoot通讯录系统全新发布! Docker快速手上视频教程(无废话版)[免费] 作者:E-iceblue https://www.cnblo ...

  6. java操作跨页的word cell_Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行...

    本文将对如何在Java程序中操作Word表格作进一步介绍.操作要点包括 如何在Word中创建嵌套表格. 对已有表格添加行或者列 复制已有表格中的指定行或者列 对跨页的表格可设置是否禁止跨页断行 创建表 ...

  7. Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行

    本文将对如何在Java程序中操作Word表格作进一步介绍.操作要点包括 如何在Word中创建嵌套表格. 对已有表格添加行或者列 复制已有表格中的指定行或者列 对跨页的表格可设置是否禁止跨页断行 创建表 ...

  8. Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行...

    点击上方 "程序员小乐"关注公众号, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 Destiny decides who enters your lif ...

  9. excel表格行宽列高怎么设置_excel的行高列宽怎么设置_excel的行高和列宽在哪设置...

    在使用excel时,行高和列宽一定程度上影响着整个表格的美观程度,下面为你分享了几个关于行高列宽的超实用的小技巧,感兴趣的小伙伴快来看看吧! 1.行高的单位像素怎么更改为厘米? 在设置表格时,要求设置 ...

最新文章

  1. Hibernate 查询数据库中的数据
  2. HDU1753 大明A+B(大数相加)(Java题解)
  3. 【Windows 逆向】OD 调试器工具 ( OD 工具简介 | OD 工具与 CE 工具对比 )
  4. 【mysql问题】foreign key without name 解决方法
  5. 如何动态改变框架的大小[转]
  6. Dubbo 只注册,只订阅
  7. selenium定位输入框_[Selenium 粗浅笔记] 用Selenium填写表单
  8. 合肥工业大学第六届“互联网+”大学生创新创业大赛项目计划书:AI云学习 —— 一款基于Spark构建知识图谱的人工智能学习工具
  9. 也许你需要看看这篇文章
  10. domain adaptation 领域自适应
  11. 计算机音乐出山,《出山》音乐
  12. 维度诅咒_维度的诅咒减去行话的诅咒
  13. 一键清理系统垃圾.bat文件中的误区,你了解吗?
  14. 云服务器哪家好?阿里云国际版还是华为云国际版?
  15. 支付宝转账又出新方法:悬浮条自动识别输入,避免失误尴尬
  16. 5G·深·体验1:5G到底有多快?
  17. 【数据产品案例】阿里XSigma智能客服调度平台
  18. K12教育小初高各个版本教材内的章节数据
  19. (华硕)笔记本电脑启动提示BOOTMEG is missing
  20. 关闭VM中虚拟机与主机时间同步

热门文章

  1. 2022 年已经铜三铁四,金九银十还会有吗?
  2. Mybatis实现增删改查
  3. STM32CubeMX配置注意事项
  4. 企业选择大数据应用程序,需要考虑哪些因素?
  5. java毕业项目:基于SSM的医院在线预约挂号系统1020
  6. php pager,Pear::Pager分页类简介_PHP教程
  7. python定义函数以什么开头_python中下划线开头函数是什么
  8. numpy中向量的基本操作
  9. 使用H5Stream实现rtsp流播放,并整合到web项目中
  10. dev、test、prod是什么?