首页 > 其他分享 >数仓如何递归查询视图依赖

数仓如何递归查询视图依赖

时间:2024-01-24 10:12:19浏览次数:26  
标签:数仓 递归 refobjname 视图 查询 dependency view

本文分享自华为云社区《GaussDB(DWS)如何递归查询视图依赖》,作者:半岛里有个小铁盒。

1. 前言

适用版本:【8.1.0(及以上)】

本文通过介绍with recursive递归查询的办法来实现查询视图的层级依赖关系

2. 实现简介

对于postgres生态来说,视图的依赖关系没有现成的查询方法,需要对系统表pg_depend及pg_rewrite编写复杂的组合查询才能得知,而对于Oracle和MySql,该需求都较易实现,分别查询USER_DEPENDENCIES和INFORMATION_SCHEMA.VIEWS即可轻易查出,因此在pg生态来说有必要编写一个直观的视图来查看各个视图与基表或与其他视图的层级依赖关系。本文通过with recursive递归查询的办法来实现视图的层级依赖关系查询。效果如下:

img

首先建立两个基表t1、t2,表结构随意,再建立一系列的视图进行层级关联,关联关系也随意。本文的建表及视图语句如下:

create table t1 (a int, b int) distribute by hash(a);
create table t2 (a int, b int) distribute by hash(a);
create view v1 as select * from t1;
create view v2 as select * from v1;
create view v3 as select * from v2;
create view v4 as select * from v3;
create view v5 as select * from t2;
create view v6 as select * from v5;
create view v7 as select * from v6;
create view v8 as select * from v2;

实际的局点中,用户的视图依赖关系肯定要比这复杂得多,本文仅讲解原理。对于上述的视图依赖关系,可以通过如下查询得出:

SELECT c.ev_class::regclass::varchar AS objname, pc.oid::regclass::varchar AS refobjname, pc.relkind AS relkind
     FROM pg_depend a,pg_depend b,pg_class pc,pg_rewrite c
    WHERE a.refclassid=1259
      AND a.classid=2618
      AND b.deptype='i'
      AND a.objid=b.objid
      AND a.classid=b.classid
      AND a.refclassid=b.refclassid
      AND a.refobjid<>b.refobjid
      AND pc.oid=a.refobjid
      AND c.oid=b.objid
      AND (a.objid>=16384 or a.refobjid>=16384)
      GROUP BY c.ev_class,pc.oid,pc.relkind
  ORDER BY relkind;

其中倒数第二行的16384表示过滤掉系统对象,relkind表示上级依赖对象的类型,r说明依赖于基表,v表示依赖另一个视图。其查询结果如下:

img

可见这种查询并不直观,只能通过肉眼分析得出递归的依赖关系,对用户并不友好。莫急,先将上述查询保存为视图,例如起名为PUBLIC.gs_view_dependency。接下来我们来学习一下with recursive语法的使用方法,从pg官网可以get到的知识是,WITH语句通常被称为通用表表达式(Common Table Expressions)或者CTEs。WITH语句作为一个辅助语句依附于主语句,WITH语句和主语句都可以是SELECT,INSERT,UPDATE,DELETE中的任何一种语句。WITH语句还可以通过增加RECURSIVE修饰符来引入它自己,从而实现递归:

img

WITH RECURSIVE语句包含了两个部分:

  • (非递归部分)non-recursive term,即上图中的union all前面的部分
  • (递归部分)recursive term,即上图中union all后面的部分

执行步骤如下:

执行non-recursive term。(如果使用的是union而非union all,则需对结果去重)其结果作为recursive term中对result的引用,同时将这部分结果放入临时的working table中

重复执行如下步骤,直到working table为空:用working table的内容替换递归的自引用,执行recursive term,(如果使用union而非union all,去除重复数据),并用该结果(如果使用union而非union all,则是去重后的结果)替换working table

因此,照葫芦画瓢,我们可以先给这个CTE查询起个名字,例如:

WITH RECURSIVE get_view_dependency
AS
( ... )

然后,我们可以把非递归部分写成:

SELECT a.objname, a.refobjname, a.refobjname path FROM PUBLIC.gs_view_dependency a where a.relkind = 'r'

因为查找到类型为’r’的基表的时候,递归就应该结束了。并且我们需要将refobjname组装成一条path来实现依赖路径的直观表示。因为是递归,所以我们需要不止一次的调用PUBLIC.gs_view_dependency,因此我们给它起个别名a。而递归的条件显而易见,应该是用refobjname来与objname做内关联,因此我们可以写作:

INNER JOIN get_view_dependency cte ON b.refobjname=cte.objname

其中cte就用来指代上一次的递归查询结果,而递归的退出条件就应该是最开始写的类型为’r’的情况。其中b就应该是递归部分每次调用的PUBLIC.gs_view_dependency。而我们除了要查询objname和refobjname外,更重要的是要组成一个path,而path每个节点最好通过一个’->'来直观表示,因此递归部分我们就可以写成:

SELECT b.objname, b.refobjname, cte.path ||' -> '|| b.refobjname path FROM PUBLIC.gs_view_dependency b
INNER JOIN get_view_dependency cte ON b.refobjname=cte.objname

因此,整个CTE递归查询便可以写成:

WITH RECURSIVE get_view_dependency
AS
(
SELECT a.objname, a.refobjname, a.refobjname path FROM PUBLIC.gs_view_dependency a where a.relkind = 'r'
UNION ALL
SELECT b.objname, b.refobjname, cte.path ||' -> '|| b.refobjname path FROM PUBLIC.gs_view_dependency b
INNER JOIN get_view_dependency cte ON b.refobjname=cte.objname
)
SELECT * FROM get_view_dependency;

为了方便以后的使用,我们可以给它起个名字保存起来,例如CREATE VIEW PUBLIC.gs_view_table_dependency AS …。效果就是文章开头所示那样,便大功告成。

3. 总结

在数据库中,查询视图是一种非常有用的工具,它可以帮助我们更好地组织和管理数据。然而,查询视图的层级依赖关系可能会让人感到困惑。本文将介绍一种通过 with recursive 递归查询的办法来实现查询视图的层级依赖关系的方法,希望对你有所帮助。

 

点击关注,第一时间了解华为云新鲜技术~

 

标签:数仓,递归,refobjname,视图,查询,dependency,view
From: https://www.cnblogs.com/huaweiyun/p/17983991

相关文章

  • 使用递归解决嵌套页面的状态改变
    场景一个注销页,里面有四种状态。注销说明页输入手机号码和图形验证码输入短信验证码注销处理中在每一个状态中,都需要被APP调用window.jumpOther()返回到上一个状态<template><divv-if="pageStatus.isDelete"></div><divv-if="pageStatus.isInputPhone"></div......
  • 【8.0】死锁和递归锁
    【一】死锁【1】介绍死锁是指两个或多个进程,在执行过程中,因争夺资源而造成了互相等待的一种现象。即两个或多个进程持有各自的锁并试图获取对方持有的锁,从而导致被阻塞,不能向前执行,最终形成僵局。在这种情况下,系统资源利用率极低,系统处于一种死循环状态。【2】示例f......
  • SQL构建表层次关系,递归累加数据
     构建表的上下级关系      有一个需求,表中数据没有关系,如同一个类型的,有多个出库时间。代码--构建表的上下级关系--可以对同一个产品的,有层次关系--使用ROW_NUMBER(),来构建,最上上一级为0INSERTINTOStock([no]--编号,[quantity]......
  • 遍历二叉树非递归实现
    实现1.前序遍历publicvoidpreOrderNor(TreeNoderoot){if(root==null){return;}Stack<TreeNode>stack=newStack<>();stack.push(root);while(!stack.isEmpty()){TreeNodecur......
  • 【Qt之模型视图】5. Qt库提供的视图便捷类
    1.前言Qt提供了一些便捷的视图类,如QListWidget提供项目列表,QTreeWidget显示多级树结构,QTableWidget提供单元格项的表格。每个类都继承了QAbstractItemView类的行为,QAbstractItemView类实现了项目选择和标题管理的通用行为。这三个类使用起来方便,但适合于少量数据的存储与显示(存......
  • 【电商数仓6.0】笔记1
    采集项目&数据仓库项目(是企业中数据管理平台中的两个核心管理模块)采集项目:数据采集,传输为主(flume,kafka,datax,maxwell)数据仓库:以计算为主,同时存储数据(mysql,HDFS,Spark,Flink,MR,Hive) 数据库&数据仓库数据库database来源:企业中基础核心的业务数据存储:查找数......
  • MySQL 视图
    视图(View)是一种虚拟存在的表,视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图只保存了查询的SQL逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。创建CREATE[......
  • 详解匿名函数递归:从此能看懂天书代码
    最近在读《左耳听风》,里面提到了一个匿名函数递归的例子,觉得很有趣,但是我觉得书里讲解的还是有点难懂,所以尝试用自己的理解把这个问题重新讲了一遍。注:本文中所用的代码示例会同时使用JavaScript,Python语言。让我们先来看下面这段代码://javascript(f=>f(f))(f=>n=>n==......
  • 三视图
    三视图的投影规律是什么2024-01-0916:4450人阅读三视图的投影规律是主俯长对正、主左高平齐、俯左宽相等。主视图和俯视图的长要相等;主视图和左视图的高要相等;左视图和俯视图的宽要相等。一般必须将形体向几个方向投影,才能完整清晰地表达出形体的形状和结构。三视图的......
  • 【Qt之模型视图】3. 视图类及使用
    1.概念在MVC架构中,视图通过与模型交互,将数据项进行显示。在此还需要再一次声明,数据的呈现方式可能与底层存储数据项的数据结构完全不同。数据和显示能够分离,是因为使用了QAbstractItemModel提供了统一接口,和QAbstarctItemView提供了一个标准视图接口,以及使用模型索引提供了一个......