基于Python-sqlparse的SQL表血缘追踪解析实现

news2025/1/10 11:44:48

目录

前言

一、主线任务

1.数据治理

2.血缘追踪

3.SQL表血缘

二、实现过程

1.目标效果

2.代码实现

1.功能函数识别

2.SQL标准格式

 3.解析AST树

4.最终效果:

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢


前言

之前我在两篇SQLparse的开源库解析中就说过自己在寻找在python编程内可行的SQL血缘解析,JAVA去解析Hive的源码实践的话我还是打算放到后期来做,先把Python能够实现的先实现完。主要是HiveSQL的底层就是JAVA代码,怎么改写还是绕不开JAVA的。不过上篇系列我有提到过sqlparse,其实这个库用来解析血缘的话也不是不可以,但是能够实现的功能是有限的,目前我实验还行,一些较为复杂的SQL也能解析得出,算是成功达到可部署服务的水准了,但是根据SQL格式来匹配的话肯定是有些SQL格式不能完全匹配成功的,如果大家有需要血缘分析的SQL可以再次验证一下。

算是填完了之前的部分坑,目前的开发进度已经可以将SQL的表血缘分析追踪实现了,实现字段血缘的功能开发等后续将陆续上线。


一、主线任务

首先来对该项目的目标来分析一下,说到SQL血缘分析,这偏向于数据治理。

1.数据治理

数据治理(Data Governance)是组织中涉及数据使用的一整套管理行为。数据要产生价值,需要一个合理的“业务目标”,数据治理的所有活动应该围绕真实的业务目标而开展,建立数据标准、提升数据质量只是手段,而不是目标。

数据治理的本质是管理数据,因此需要加强元数据管理和主数据管理,从源头治理数据,补齐数据的相关属性和信息,比如:元数据、质量、安全、业务逻辑、血缘等,通过元数据驱动的方式管理数据生产、加工和使用。

数据的质量直接影响着数据的价值,并且直接影响着数据分析的结果以及我们以此做出的决策的质量。数据模型血缘与任务调度的一致性是建管一体化的关键,有助于解决数据管理与数据生产口径不一致的问题,避免出现双重管理不一致的低效管理模式。

2.血缘追踪

数据被业务场景使用时,发现数据错误,数据治理团队需要快速定位数据来源,修复数据错误。那么数据治理团队需要知道业务团队的数据来自于哪个核心库,核心库的数据又来自于哪个数据源头。我们的实践是在元数据和数据资源清单之间建立关联关系,且业务团队使用的数据项由元数据组合配置而来,这样,就建立了数据使用场景与数据源头之间的血缘关系。 数据资源目录:数据资源目录一般应用于数据共享的场景,例如政府部门之间的数据共享,数据资源目录是基于业务场景和行业规范而创建,同时依托于元数据和基础库主题而实现自动化的数据申请和使用。

也就是为什么我们需要解析SQL,追踪建表索引或者引用解析。

3.SQL表血缘

那么其中最重要的就是关于各个数据库之间的数据关系了,关于建表以及插入更新操作都会使数据发生一定的改变,那么这些操作就一定是被允许的?就像原来在网上看到的某某公司程序员删库跑路,或者是一不小心删错数据导致耽误产研线等等。为了防止以上事故的出现必定要为此操作上一层保险,为每个成员设定数据操作权限。这样以来提交的SQL语句就多了一层判断。

二、实现过程

1.目标效果

首先明白一点我们要做出的东西需要呈现一个怎样的形式,其中位于行业前排的无疑是SQLFlow:

 当第一次看到此图我就决定血缘追踪就应该是这个样子,能够清晰的解析出每个字段和表之间的血缘关系。以此我们设定输出的基准,我们要做的项目目标就是如此。

2.代码实现

1.功能函数识别

该功能也是必须要实现的功能,我们需要明白这个SQL主要是干什么事情的。如果是插入INSERT或者是CREATE就有血缘分析的必要,如果是SELECT的话那么做简单的SQL解析即可。有了研究sqlparse源码的成果我们调用相应的函数即可:

sql="select * from table1;insert into table select a,b,c from table2"

if __name__ == '__main__':
    table_names=[]
    #sql=get_sqlstr('read_sql.txt')
    stmt_tuple=analysis_statements(sql)
    for each_stmt in stmt_tuple:
        type_name=get_main_functionsql(each_stmt)
        print(type_name)

输出:

 那么对于SELECT我们就SQL涉及到的表追溯即可:

对于CREATE和INSERT的做血缘即可:

2.SQL标准格式

对于传入的SQL我们首先要让这条语句符合标准的SQL语句格式,这样对于传输格式保持一致,兼容很有作用。一般我们都是通过文本来读入。故需要读取文本做处理:

原始文本:

 处理后:

if __name__ == '__main__':
    sql=get_sqlstr('read_sql.txt')
    print(sql)

 3.解析AST树

得到的SQL无论是ANTRL还是SQLPARSE都是解析为一棵树的形式进行递归回溯。最终都要解析生产的SQL树:

sql="select * from table1;insert into table3 select a,b,c from table2"

if __name__ == '__main__':
    #sql=get_sqlstr('read_sql.txt')
    stmt_tuple=analysis_statements(sql)
    for each_stmt in stmt_tuple:
        table_names=[]
        type_name=get_main_functionsql(each_stmt)
        get_ASTTree(each_stmt)

 

4.最终效果:

SQL:


select
b.product_name "产品",
count(a.order_id) "订单量",
b.selling_price_max "销售价",
b.gross_profit_rate_max/100 "毛利率",
case when b.business_type =1 then '自营消化' when b.business_type =2 then '服务商消化'  end "消化模式"
from(select 'CRM签单' label,date(d.update_ymd) close_ymd,c.product_name,c.product_id,
    a.order_id,cast(a.recipient_amount as double) amt,d.cost
    from mysql4.dataview_fenxiao.fx_order a
    left join mysql4.dataview_fenxiao.fx_order_task b on a.order_id = b.order_id
    left join mysql7.dataview_trade.ddc_product_info c on cast(c.product_id as varchar) = a.product_ids and c.snapshot_version = 'SELLING'
    inner join (select t1.par_order_id,max(t1.update_ymd) update_ymd,
                sum(case when t4.product2_type = 1 and t5.shop_id is not null then t5.price else t1.order_hosted_price end) cost
               from hive.bdc_dwd.dw_mk_order t1
               left join hive.bdc_dwd.dw_mk_order_status t2 on t1.order_id = t2.order_id and t2.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
               left join mysql7.dataview_trade.mk_order_merchant t3 on t1.order_id = t3.order_id
               left join mysql7.dataview_trade.ddc_product_info t4 on t4.product_id = t3.MERCHANT_ID and t4.snapshot_version = 'SELLING'
               left join mysql4.dataview_scrm.sc_tprc_product_info t5 on t5.product_id = t4.product_id and t5.shop_id = t1.seller_id
               where t1.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
               and t2.valid_state in (100,200) ------有效订单
               and t1.order_mode = 10    --------产品消耗订单
               and t2.complete_state = 1  -----订单已经完成
               group by t1.par_order_id
    ) d on d.par_order_id  = b.task_order_id
    where c.product_type = 0 and date(from_unixtime(a.last_recipient_time)) > date('2016-01-01') and a.payee_type <> 1 -----------已收款
    UNION ALL
    select '企业管家消耗' label,date(c.update_ymd) close_ymd,b.product_name,b.product_id,
    a.task_id,(case when a.yb_price = 0 and b.product2_type = 1 then b.selling_price_min else a.yb_price end) amt,
    (case when a.yb_price = 0 and b.product2_type = 2 then 0 when b.product2_type = 1 and e.shop_id is not null then e.price else c.order_hosted_price end) cost
    from mysql8.dataview_tprc.tprc_task a
    left join mysql7.dataview_trade.ddc_product_info b on a.product_id = b.product_id and b.snapshot_version = 'SELLING'
    inner join hive.bdc_dwd.dw_mk_order c on a.order_id = c.order_id and c.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
    left join hive.bdc_dwd.dw_mk_order_status d on d.order_id = c.order_id and d.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
    left join mysql4.dataview_scrm.sc_tprc_product_info e on e.product_id = b.product_id and e.shop_id = c.seller_id
    where  d.valid_state in (100,200) and d.complete_state = 1  and c.order_mode = 10
    union ALL
    select '交易管理系统' label,date(t6.close_ymd) close_ymd,t4.product_name,t4.product_id,
    t1.order_id,(t1.order_hosted_price-t1.order_refund_price) amt,
    (case when t1.order_mode <> 11 then t7.user_amount when t1.order_mode = 11 and t4.product2_type = 1 and t5.shop_id is not null then t5.price else t8.cost end) cost
    from hive.bdc_dwd.dw_mk_order t1
    left join hive.bdc_dwd.dw_mk_order_business t2 on t1.order_id = t2.order_id and t2.acct_day=substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
    left join mysql7.dataview_trade.mk_order_merchant t3 on t1.order_id = t3.order_id
    left join mysql7.dataview_trade.ddc_product_info t4 on t4.product_id = t3.MERCHANT_ID and t4.snapshot_version = 'SELLING'
    left join mysql4.dataview_scrm.sc_tprc_product_info t5 on t5.product_id = t4.product_id and t5.shop_id = t1.seller_id
    left join hive.bdc_dwd.dw_fact_task_ss_daily t6 on t6.task_id = t2.task_id and t6.acct_time=date_format(date_add('day',-1,current_date),'%Y-%m-%d')
    left join (select a.task_id,sum(a.user_amount) user_amount
               from hive.bdc_dwd.dw_fn_deal_asyn_order a
               where a.is_new=1 and a.service='Trade_Payment' and a.state=1 and a.acct_day=substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
               group by a.task_id)t7 on t7.task_id = t2.task_id          
    left join (select t1.par_order_id,sum(t1.order_hosted_price - t1.order_refund_price) cost
               from hive.bdc_dwd.dw_mk_order t1
               where t1.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2) and t1.order_type = 1 and t1.order_stype = 4 and t1.order_mode = 12
               group by t1.par_order_id) t8 on t1.order_id = t8.par_order_id
    where t1.acct_day = substring(cast(DATE_ADD('day',-1,CURRENT_DATE) as varchar),9,2)
    and t1.order_type = 1 and t1.order_stype in (4,5) and t1.order_mode <> 12 and t4.product_id is not null and t1.order_hosted_price > 0 and t6.is_deal = 1 and t6.close_ymd >= '2018-12-31'
)a
left join mysql7.dataview_trade.ddc_product_info b on a.product_id = b.product_id and b.snapshot_version = 'SELLING'
where b.product2_type = 1 -------标品
and close_ymd between DATE_ADD('day',-7,CURRENT_DATE)  and DATE_ADD('day',-1,CURRENT_DATE)
GROUP BY b.product_name,
b.selling_price_max,
b.gross_profit_rate_max/100,
b.actrul_supply_num,
case when b.business_type =1 then '自营消化' when b.business_type =2 then '服务商消化'  end
order by count(a.order_id) desc
limit 10
if __name__ == '__main__':
    table_names=[]
    sql=get_sqlstr('read_sql.txt')
    
    stmt_tuple=analysis_statements(sql)
    for each_stmt in stmt_tuple:
        type_name=get_main_functionsql(each_stmt)
        blood_table(each_stmt)
        Tree_visus(table_names,type_name)
        

点关注,防走丢,如有纰漏之处,请留言指教,非常感谢

以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/526164.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

eclipse的安装与配置

1、下载 eclipse 下载地址&#xff1a;https://www.eclipse.org/downloads/ 点击 【Download Package】 找到JavaEE IDE&#xff0c;点击【Windows x86_64】 点击【Select Another Mirror】&#xff0c;然后点击国内任意一个大学镜像下载即可&#xff01; 下载成功后&…

express的使用(一)

因为有时候没有登录CSDN,所以弄了一个订阅号&#xff0c;会不定时的更新文章(其实就是在csdn这边发布了之后搬过去&#xff0c;不过有问题的可以留言&#xff0c;csdn不常上来看)&#xff0c;欢迎订阅文章链接&#xff1a;[订阅号-express的使用(一)] ------------------------…

全网首发2023全新ChatGPT3.5小程序开源源码 全新UI

源码简介&#xff1a; 2023全新ChatGPT3.5小程序开源源码 全新UI 全网首发 这一版本ui比较好看 回复速度也快了 小程序是java的 带后台 本来准备给你们带上接口的然后么后台是和接口连接的 我改什么内容你们前段都会显示所以全开源 自己搭建下吧&#xff0c;腾讯云买个国外服…

MFC基础入门

1 MFC入门 1.1 为什么学习MFC 在Windows平台上做GUI开发&#xff0c;MFC是一个不错的选择。 学习MFC不仅可以学习到MFC本身&#xff0c;而且可以学习MFC框架的设计思想。 1.2 Windows消息机制 基本概念解释 SDK&#xff1a;软件开发工具包(Software Development Kit)&…

『MySQL 实战 45 讲』15 - 两阶段提交、索引相关问题

日志和索引相关问题 mysql 两阶段提交问题 在两阶段提交的不同时刻&#xff0c;MySQL 异常重启会出现什么现象&#xff1f; 如果 crash 发生在时刻 A 由于此时 binlog 还没写&#xff0c;redo log 也还没提交&#xff0c;所以崩溃恢复的时候&#xff0c;这个事务会回滚 如果 …

数据链路层协议 ——— 以太网协议

文章目录 链路层解决的问题以太网协议认识以太网以太网帧格式认识MAC地址对比理解MAC地址和IP地址认识MTUMUT对IP协议的影响MTU对UDP协议的影响MTU对TCP协议的影响数据跨网络传输的过程 ARP协议ARP协议的作用ARP数据的格式ARP协议的工作流程 链路层解决的问题 IP拥有将数据跨网…

【前端知识】Cookie, Session,Token和JWT的发展及区别(二)

【前端知识】Cookie, Session,Token和JWT的发展及区别&#xff08;二&#xff09; 4. Session4.1 Session的背景及定义4.2 Session的特点&#x1f44d;4.2.1 Session的特点&#x1f440;4.2.2 Session保存的位置 4.3 Session的一些重要/常用属性4.4 Session的认证流程4.5 Sessi…

Python数据清洗:Python和Pandas数据清洗的实用教程

前言&#xff1a; 技术书籍是学习技术知识的重要资源之一。读技术书可以帮助我们学习新技能和知识&#xff0c;技术书籍提供了可靠的、全面的信息&#xff0c;帮助我们快速学习新技能和知识。同时技术书籍有助于保持你的竞争力&#xff0c;因为它们提供了最新的技术知识和实践。…

什么? 你还没用过 Cursor? 智能 AI 代码生成工具 Cursor 安装和使用介绍

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;蚂蚁集团高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐…

ChatGPT 免费体验来了

露个相吧 1、相信很多小伙伴们面试或者工作中会遇到数组扁平化这一问题&#xff0c;如今正是 chatgpt 大火的时候&#xff0c;何不让我们试试水呢&#xff0c;所以让我们的 chatgpt 用js帮我们写一个数组扁平化吧 2、这就&#xff1f;这就&#xff1f;这就写出来了&#xff1f…

【JavaScript数据结构与算法】字符串类(反转字符串中的单词)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端&#xff08;Node.js&#xff09; &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;…

【大数据基础】淘宝双11数据分析与预测

https://dblab.xmu.edu.cn/post/8116/ 问题 问题1 mysql登录需要密码 https://cloud.tencent.com/developer/beta/article/1142525 这个很神奇&#xff0c;我密码输1就进去了 为避免出问题&#xff0c;把解决方案放这里&#xff1a; https://blog.csdn.net/qq_34771403/ar…

【路径规划】全局路径规划算法——蚁群算法(含python实现)

文章目录 参考资料1. 简介2. 基本思想3. 算法精讲4. 算法步骤5. python实现 参考资料 路径规划与轨迹跟踪系列算法蚁群算法原理及其实现蚁群算法详解&#xff08;含例程&#xff09;图说蚁群算法(ACO)附源码蚁群算法Python实现 1. 简介 蚁群算法&#xff08;Ant Colony Algo…

mybatis-plus 自动填充的时间跟真实时间相差8小时

项目中 用到了以下两个字段,分别是插入数据时间和更新数据时间&#xff0c;用的mybatis-plus自动填充,结果发现填充的时间跟真实时间相差很多。查了一些资料&#xff0c;找到了解决方案&#xff1a; 1. 下图是我的mysql没有进行配置之前的时区配置,这里的CST包括了4个时区,分别…

一百零六、Hive312的计算引擎由MapReduce(默认)改为Spark(亲测有效)

一、Hive引擎包括&#xff1a;默认MR、tez、spark 在低版本的hive中&#xff0c;只有两种计算引擎mr, tez 在高版本的hive中&#xff0c;有三种计算引擎mr, spark, tez 二、Hive on Spark和Spark on Hive的区别 Hive on Spark&#xff1a;Hive既存储元数据又负责SQL的解析&…

【0基础】学习solidity开发智能合约-初识solidity

本篇课程开始&#xff0c;我们来学习一下如何使用solidity开发智能合约&#xff0c;由于博主对于solidity的学习&#xff0c;也是自学的&#xff0c;所以一些不足或有纰漏之处还望指出&#xff0c;大家共同进步&#xff0c;本系列课程会分很多节课讲述&#xff0c;从入门到进阶…

安装navicat详细流程

1.双击已下载好的navicat安装包&#xff0c;点击"下一步" 2.点击我同意&#xff0c;在点击"下一步" 3.设置navicat安装路劲&#xff0c; 至少要保证磁盘有90M的空间。在这里选择默认的安装路径&#xff0c;也可以根据自身情况安装到其他盘。 4.默认&#x…

一个几乎全民都会的算法——二分查找

为什么说二分查找是全民都会的算法&#xff1f; 20年前央视2套有一档叫《幸运52》的综艺节目&#xff0c;其中一个环节叫《幸运超市》&#xff0c;每一期已故著名主持人咏哥都会给佳宾们出示几个商品&#xff0c;凡是佳宾猜中价格的&#xff0c;就能获赠这件商品。这档节目红极…

C++ 类和对象(中)构造函数 和 析构函数 ,const成员

上篇链接&#xff1a;C 类和对象&#xff08;上&#xff09;_chihiro1122的博客-CSDN博客 类的6个默认成员函数 我们在C当中&#xff0c;在写一些函数的时候&#xff0c;比如在栈的例子&#xff1a; 如上述例子&#xff0c;用C 返回这个栈是否为空&#xff0c;直接返回的话&am…

Selenium+Pytest自动化测试框架实战

前言 1、Selenium是一个免费的(开源)自动化测试组件&#xff0c;适用于跨不同浏览器和平台的Web应用程序【selenium是一个自动化工具&#xff0c;而不是自动化框架】。它非常类似于HP Quick Test Pro (QTP现在叫UFT)&#xff0c;只是Selenium侧重于自动化基于Web的应用程序。使…