【教程】利用宜撘实现自动生成业务SQL功能

本文涉及的产品
大数据开发治理平台DataWorks,Serverless资源组抵扣包300CU*H
简介: 模板地址: https://yida.alibaba-inc.com/newApp.html?#/template/TPL_LPS8OWKVUIEHEVM80XFN?_k=z3r1e4 背景: 之前在内网上有讨论SQL算不算是编程语言,一石激起千层浪,大家参与度非常高,有很多运营同学也表示会用SQL,我觉得这个是很好的现象。编程语言只是解决问题的工具,黑猫白猫,能抓到老鼠就是好猫。 这个问

模板地址:

https://yida.alibaba-inc.com/newApp.html?#/template/TPL_LPS8OWKVUIEHEVM80XFN?_k=z3r1e4

背景:

之前在内网上有讨论SQL算不算是编程语言,一石激起千层浪,大家参与度非常高,有很多运营同学也表示会用SQL,我觉得这个是很好的现象。编程语言只是解决问题的工具,黑猫白猫,能抓到老鼠就是好猫。

这个问题也侧面说明了SQL确实是一门上手难度低的语言,因为SQL语法相对简单,而且集团又有DataWorks这种线上运行SQL的工具,不需要本地配置各种复杂的环境,再加上几乎所有业务线都有专门的数据研发同学会建立相应的数据仓库,尽可能地减少使用同学的多表JOIN操作,使得没有编程基础的同学也可以很快的使用SQL解决自己的数据需求。

但是在实际业务场景中,还是有很多同学不能很好地使用SQL,还是有很多的临时取数的需求。大家用不好SQL的原因总结为以下几个痛点:

  1. 不会SQL语法
  2. 不知道要用哪张表
  3. 不知道要用哪个字段
  4. 不知道字段里都有哪些值
  5. 不知道特殊的业务逻辑

一般的做法是维护各种教程、文档、使用说明、积累SQL模板等等,但是实际效果并不理想,因为业务经常变动维护文档确实也是一件麻烦事,而且一旦字段多了以后看文档都能晕掉。

如果你也在为上面的问题而苦恼,那下面说的解决方案或许会帮到你

界面截图:

功能说明:

  1. 根据选择的筛选条件动态生成SQL
  2. 下拉列表内容为接口返回,不需要人工手动维护
  3. 所有输入都有格式检查,防止输入错误数据
  4. 可以使用之前的配置JSON快速生成SQL

有同学会问了,实现这些功能需要额外的前端后端的资源,但是我们团队的资源很紧张,没有余力开发一个这样的工具怎么么办?

完全不用担心,你们看到的功能全都是基于现有的工具做的,不需要从0开始开发。

用到的工具有:

  1. 宜撘/(界面)
  2. DataWorks的(数据提供)

下面我会一步一步教大家搭建一个属于自己业务的自动化SQL生成工具。

--------------------------------------- 我是分割线 -----------------------------------

1. 搭建界面

本教程使用宜撘演示,乐高比宜撘更自由,上手难度更高。

    根据自己的业务经验总结出来常用的筛选条件,设置筛选条件,原则上能通过下拉选择完成的就不要用输入框,要相信 永远不要相信用户的输入 实在需要用输入框,则一定要对输入进行校验。

宜撘可以很方便的设置一些简单的校验规则,如果需要更高级的操作,可以通过自定义函数解决

格式校验的代码网上搜有很多例子,下面是一个只允许输入英文(小写)及数字及下划线的校验函数:

function validateRule(value) {
  var re =  /^[0-9a-z_]+$/;
  return re.test(value)
}

 

我们有很多的筛选条件,但是用户不一定会用到所有的条件,我们希望当用户需要某个筛选条件的时候显示对应的输入框,其他不需要的隐藏掉。宜撘可以很方便的设置这个功能:

大家看图应该就能理解,就不具体描述了。

搭建界面的部分是最简单的,几乎不用代码就可以完成

 

2. 设置数据源

    很多时候我们的筛选条件是枚举值,但是这个值会很多而且还会变化,我们不想每次发生变化的时候去手动修改,那就可以用DataWorks的数据服务功能,这个功能可以将ODPS表封装为一个HTTP的接口供宜撘来调用。数据服务教程:https://www.atatech.org/articles/120600

建好数据服务接口以后就可以配置宜撘的数据源来调用这个接口:选择远程数据源,直接将HTTP的链接复制到URL里面,方法选择GET就可以了

但是我们会发现通过数据服务返回的数据格式不能直接用于下拉框的展示组件,需要我们进行格式处理,宜撘也提供这个处理接口,在数据源的 DID 输入框里面可以进行数据格式的处理。下拉框和多选的数据格式为:

{
    "options":[
        {
            "text":"选项一",
            "value":"1"
        },
        {
            "text":"选项二",
            "value":"2"
        }
    ]
}

 

用我自己的处理方法做个例子:

function didFetch(content, ctx) {
  // alert(JSON.stringify(content));
  var dp = ctx.getDataPool();
  // 拼接成下拉框需要的格式
  var result = {};
  var options = new Array();
  for (var i = 0; i < types.length; i++) {
    var type_content = new Object();
    type_content.text = types[i].task_type;
    type_content.value = types[i].task_type;
    options.push(type_content);
  }
  result.options = options;
}

 

根据实际的DataWork数据服务的返回格式进行修改就可适配不同的组件。

但是有的时候我们需要根据选择的内容作为参数动态的去请求返回值,宜撘也提供了这个功能:文档

例如我要根据我选择的任务类型去请求服务,新建一个变量类型的数据源selected_task_type 

然后在需要传参的数据源里面配置参数,需要注意的是变量参数的顺序一定要在引用这个变量的数据源之前

3. 设置输入后动作

    我们希望可以在每一个输入框的值发生变动之后,动态的对SQL进行生成,可以使用宜撘的动作设置功能。文档:https://yuque.antfin-inc.com/legao/legao/events-call

由于宜撘目前没有对于表单的表单ID(只有唯一标识而且不能修改,使用起来不方便)的设置,所以在这里我用传入的参数key来告诉处理方法目前操作的是什么对象。

/**
 * 更新querry
 */
export function updateQueryString(ctx) {
  var dp = ctx.getDataPool();
  var task_tag;
  var table_name;
  // 1.获取当前更新的key
  var query_key = ctx.params.key;
  // 2.获取变更的值
  var query_value = ctx.state.getValue('fieldData/value');
  // 如果是导入的json则直接赋值
  if(query_key == "full_query_json"){
    dp.setValue("query_str", query_value); 
    var sql_string = createSQL(query_str_json);
    dp.setValue("sql_string", sql_string); 
  }else{
    // 3.如果是选择任务类型,则更改已选择任务类型
    if(query_key == "task_type"){
      // alert("原始任务类型: "+ctx.store.get('selected_task_type'));
      dp.setValue("selected_task_type", query_value); 
    }
    // console.log(JSON.stringify(query_value));
    // 3.更新请求参数
    var old_qyery_str = ctx.store.get('query_str');
    // alert("原始参数: " + old_qyery_str);
    var json_obj;
    // alert('参数: '+ old_qyery_str);
    try{
      json_obj = JSON.parse(old_qyery_str);
    }catch(err){
      json_obj = new Object();
    }
    json_obj[query_key] = query_value;
    if(query_key == "task_type"){
      var type_map = ctx.store.get("task_table_map").getValue();
      // alert(type_map);
      var task_info = JSON.parse(type_map);
      for ( var i = 0; i 

其中query_str就是用于存储生成的JSON的变量,同样也需要在数据源中定义,如果想在界面上显示的话,直接在输入框中输入 ${query_str} 即可

4. 生成SQL

    根据上一步生成的js对象进行处理,拼接SQL显示在界面上即可,这个步骤与业务强相关,需要大家根据自己的业务进行高度定制,上面代码中的 createSQL()方法。在这里我只举一个简单的例子:

/**
 * 根据JSON生成SQL
 */
function createSQL(cfg_json) {
  var task_info = JSON.parse(cfg_json);
  var task_type = task_info.task_type;
  var table_name = task_info.table_name;
  var querry_option = task_info.querry_option;
  var is_save = "and   t1.is_save = 'Y' \n";
  if(task_info.is_save == "归档"){
    is_save = "and   t1.is_save = 'Y' \n";
  }else{
    is_save = "";
  }
  var total_cnt_limit = "";
  var id_filiter = "";
  var mark_criterion_filiter = "";
  var date_filiter = "";
  var time_filiter = "";
  var speed_filiter = "";
  var weather_filiter = "";
  var channel_filiter = "";
  try{
    // 循环判断筛选条件
    for(var i = 0 ; i < querry_option.length ; i ++){
      var key = querry_option[i];
      if(key == "限制总数"){
        total_cnt_limit = "order by rand() desc \nlimit " + task_info.rec_num + " \n";
      }
      if(key == "根据日期"){
        date_filiter = "";
        if(task_info.date_filiter.startDate != null){
          var date = new Date(task_info.date_filiter.startDate);
          var Y = date.getFullYear();
          var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1);
          var D = (date.getDate() < 10 ? '0'+(date.getDate()) : date.getDate());
          date_filiter += "and   to_char(t1.log_time,'yyyymmdd') >= '" + Y + M + D + "' \n"
        }
        if(task_info.date_filiter.endDate != null){
          var date = new Date(task_info.date_filiter.endDate);
          var Y = date.getFullYear();
          var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1);
          var D = (date.getDate() < 10 ? '0'+(date.getDate()) : date.getDate());
          date_filiter += "and   to_char(t1.log_time,'yyyymmdd') <= '" + Y + M + D + "' \n"
        }
      }
      if(key == "根据时间"){
        time_filiter = "";
        if(task_info.start_time != null){
          time_filiter += "and   substr(t1.log_time,12,2) >= '" + task_info.start_time + "' \n"
        }
        if(task_info.end_time != null){
          time_filiter += "and   substr(t1.log_time,12,2) <= '" + task_info.end_time + "' \n"
        }
      }
  }catch(err){
    console.error(err);
  }
  var sql ="drop table if exists aicar_" + task_info.task_tag + "_" + task_info.task_id +"; \n"
          +"create table if not exists aicar_" + task_info.task_tag + "_" + task_info.task_id +" as \n"
          +"select distinct\n"
          +"        t1.uid \n"
          // +"      , t1." + task_info.task_tag + "_id as file_id \n"
          +"      , coalesce(t1.image_id,t1.pcd_id) as file_id \n"
          +"      , t1.car_id \n"
          +"      , t1.position \n"
          +"      , t1.speed \n"
          +"      , t1.extra_info1 \n"
          +"      , t1.results_json \n"
          +"      , t1.fmt_results_json \n"
          +"from  " +  table_name + " t1 \n"
          +"where t1.ds = max_pt('" + table_name + "') \n"
          +"and   t1.task_type = '" + task_type + "' \n"
          +is_save
          +id_filiter
          +mark_criterion_filiter
          +date_filiter
          +time_filiter
          +speed_filiter
          +weather_filiter
          +channel_filiter
          +"and   t1.is_valid = 'Y' \n"
          +"and   t1.is_empty = 'N' \n"
          +"and   t1.is_trap = 'N' \n"
          +total_cnt_limit
          +";";
  return sql;
}

根据以上步骤就可以实现自动生成SQL的功能了~直接复制生成的SQL到D2执行就可以了~希望这个方法可以让广大数据研发同学从枯燥的临时取数工作中解脱出来~提升工作效率~

 

 

 

什么?连复制粘贴运行都懒得做?想一键自动执行得到结果?虽然麻烦一点~不过这个需求也是可以满足的:

5. 调用HSF执行SQL(可选)

<

    2. 方舟流程平台(预计4月下旬对外BU开放使用)

    DataWorks不久之前新发布的手动业务流程功能可以通过调用执行,可以通过API接收参数并执行相应的处理。例如将上述界面中的配置JSON作为参数掺入,然后在DataWorks中使用PyODPS节点用Python解析JSON然后再拼接SQL。

    DataWorks手动业务流程可以通过API的方式调用,文档:https://yuque.antfin-inc.com/docs/share/f41a863a-1494-4d62-b6fb-4dccc59deff9#ezchau

    在本案例中我使用的是人工智能实验室的方舟流程平台对接,方舟已经实现了这个接口的组件,方舟平台预计4月下旬开发外BU使用。由于没有对外使用,在这里先不做介绍,等对外开放的时候会有使用的介绍。目前用到的功能就是对手动业务流程的API做了一层封装,并且可以可视化的编辑流程,调用各种服务(包括HSF),也可以使用HSF的方式进行调用。下图是目前的界面,大家可以期待一下。

    宜撘除了提供调用HTTP的接口,还提供了调用HSF的功能(毕竟我们很多服务都是通过HSF提供的)。

设置完服务之后就可以在宜撘中进行调用,本案例以流程页面为例,选择流程编辑界面:

添加自动节点,并在动作设置中选择刚才添加的HSF服务,这个服务有两个参数,第一个是对应的方舟流程CODE,第二个就是传入手动节点的参数,在这里我们选择上面我们自己拼装的JSON参数

这样在界面上点击提交之后就会自动调用手动节点进行处理~~

 

 

 

 

你说啥???你还想不跑SQL能直接看到结果??放心。。。这都不是事儿~~

6. 使用FBI生成统计报表

直接上文档:https://yuque.antfin-inc.com/quark/help/firstpcreport

将手动流程的结果表拖入FBI做展示就OK了~新版的FBI非常好用~谁用谁知道~

宜撘也可以直接嵌入FBI报表做展示,在页面上插入HTML组件,手动编辑HTML:

相关实践学习
基于MaxCompute的热门话题分析
本实验围绕社交用户发布的文章做了详尽的分析,通过分析能得到用户群体年龄分布,性别分布,地理位置分布,以及热门话题的热度。
一站式大数据开发治理平台DataWorks初级课程
DataWorks 从 2009 年开始,十ー年里一直支持阿里巴巴集团内部数据中台的建设,2019 年双 11 稳定支撑每日千万级的任务调度。每天阿里巴巴内部有数万名数据和算法工程师正在使用DataWorks,承了阿里巴巴 99%的据业务构建。本课程主要介绍了阿里巴巴大数据技术发展历程与 DataWorks 几大模块的基本能力。 课程目标 &nbsp;通过讲师的详细讲解与实际演示,学员可以一边学习一边进行实际操作,可以深入了解DataWorks各大模块的使用方式和具体功能,让学员对DataWorks数据集成、开发、分析、运维、安全、治理等方面有深刻的了解,加深对阿里云大数据产品体系的理解与认识。 适合人群 &nbsp;企业数据仓库开发人员 &nbsp;大数据平台开发人员 &nbsp;数据分析师 &nbsp;大数据运维人员 &nbsp;对于大数据平台、数据中台产品感兴趣的开发者
目录
相关文章
|
3月前
|
SQL 数据管理 数据库
SQL语句实例教程:掌握数据查询、更新与管理的关键技巧
SQL(Structured Query Language,结构化查询语言)是数据库管理和操作的核心工具
|
3月前
|
SQL 存储 数据库
SQL在构建系统中的应用:关键要素与编写技巧
在构建基于数据库的系统时,SQL(Structured Query Language)扮演着至关重要的角色
|
3月前
|
SQL Oracle 前端开发
SQL在线查询设计器2
SQL在线查询设计器2
42 4
|
3月前
|
SQL
SQL在线查询设计器
SQL在线查询设计器
27 3
|
8月前
|
SQL 数据库
SQL主体内容一致,但是对于不同的数据库,对于SQL就可能有一些细节的拓展
SQL主体内容一致,但是对于不同的数据库,对于SQL就可能有一些细节的拓展
56 1
|
8月前
|
SQL Kubernetes 调度
DataphinV3.14 Flink SQL任务支持基于Session集群调试,模拟生产代码逻辑的调试效果
实时研发一直以来的都是通过local-debug的方式来调试开发中的Flink SQL任务,该方式有如下不足: 1. 支持的采样数据有限,且非是流式数据的调试。 2. 手动上传构造数据的方式较为繁琐,局限性较大。 为便于Flink SQL任务的调试,DataphinV3.14版本支持Flink SQL任务基于Session集群调试,期望做到像离线即席查询般方便地获取实时任务的输出结果,方便用户对线上的真实数据进行代码逻辑上的调试。
140 2
|
SQL 算法 JavaScript
在线就能用的 SQL 练习平台(附SQL学习文档)
在线就能用的 SQL 练习平台(附SQL学习文档)
629 0
|
SQL 小程序 数据可视化
|
SQL 大数据 开发者
电商项目之用户启动7dayDWS 表 SQL 实现|学习笔记
快速学习电商项目之用户启动7dayDWS 表 SQL 实现
|
SQL 存储 运维
开发限制—SQL概述
本文简单介绍了PolarDB-X语法及操作。

热门文章

最新文章