源代码:大批量SQL代码语法转换实战:PIVOT函数改写(案例1)

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介: 大批量SQL代码语法转换实战:PIVOT函数改写

### 背景:在不同数据库迁移的项目中,往往会遇到SQL语法不兼容的情况。比如有的数据库支持PIVOT函数,有的不支持。遇到这种情况,就必须对PIVOT函数进行改写。

### 问题:如果存在大量代码需要改写的情况,靠人工处理会很耗时,且容易出错。能不能通过工具实现代码语法的大批量自动转换?

### 方案:可以使用开源代码解析器 ZGLanguage 对SQL代码进行大批量自动转换

### 案例演示:

# 存在 SQL PIVOT函数 如下所示:

SELECT *
FROM (select country,state,yr,qtr,sales,cogs from table111)
PIVOT
(
    SUM(sales) AS ss1,
    SUM(cogs)  AS sc 
    FOR qtr IN 
    (
        'Q1' AS Quarter1,
        'Q2' AS Quarter2,
        'Q3' AS Quarter3,
        'Q4' AS Quarter4
    )
) tmp
;


# 使用开源 ZGLanguage 转换规则,执行转换,可得到结果:

SELECT *
FROM 
(
  select ###,###,###
         SUM (case when qtr='Q1' then sales else null end) AS Quarter1_ss1,
         SUM (case when qtr='Q2' then sales else null end) AS Quarter2_ss1,
         SUM (case when qtr='Q3' then sales else null end) AS Quarter3_ss1,
         SUM (case when qtr='Q4' then sales else null end) AS Quarter4_ss1,
         SUM (case when qtr='Q1' then cogs else null end) AS Quarter1_sc,
         SUM (case when qtr='Q2' then cogs else null end) AS Quarter2_sc,
         SUM (case when qtr='Q3' then cogs else null end) AS Quarter3_sc,
         SUM (case when qtr='Q4' then cogs else null end) AS Quarter4_sc
  from (select country,state,yr,qtr,sales,cogs from table111) 
 where qtr IN('Q1','Q2','Q3','Q4')
 group by ###,###,###
) tmp
;


# 转换规则如下所示 :

__DEF_FUZZY__             Y
__DEF_DEBUG__             N
__DEF_CASE_SENSITIVE__    N

__DEF_LINE_COMMENT__      -- 
__DEF_LINES_COMMENT__     /*     */


__DEF_STR__   __IF_KW__
<1,100>
[1,1]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
[0,100]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_

__DEF_PATH__    __FROM_PIVOT_1_1__
1              : frm         @ %__IF_KW__             | from
               : tab         @                        | __TABLE_NAME__
               : ssl         @                        + __SUB_SELECT__
               : pvt         @                        | pivot
               : x1          @                        | (
N              : fun         @                        | __NAME__        __//__ sum ....
               : fs          @                        | (
               : col1        @                        | __NAME__
               : fe          @                        | )
               : as1         @ %__IF_KW__ CAN_SKIP    | as
               : colas       @                        | __NAME__
e              : dh1         @                        | ,
1              : for         @ %__IF_KW__             | for
               : col2        @                        | __NAME__
               : in          @                        | in
               : x3          @                        | (
N              : val1        @                        | __INT__
               : val2        @                        + __STRING__
               : as2         @ CAN_SKIP               | as
               : coln        @                        | __NAME__
e              : dh          @                        | ,
1              : x4          @                        | )
               : x2          @                        | )
-------------------------------------------------------------------------
1              : frm         @                        | from
               : tab         @                        | __TABLE_NAME__
               : ssl         @                        | __SUB_SELECT__
               : pvt         @                        | pivot
               : x1          @                        | (
N              : fun         @                        | __NAME__
               : fs          @                        | (
               : col1        @                        | __NAME__
               : fe          @                        | )
               : as1         @                        | as
               : colas       @                        | __NAME__
e              : dh1         @                        | ,
1              : for         @                        | for
               : col2        @                        | __NAME__
               : in          @                        | in
               : x3          @                        | (
N              : val1        @                        | __\b__
               : val2        @                        | __\b__
               : col2        @                        | __NAME__
               : col2        @                        | =
               : val1        @                        | __INT__
               : val2        @                        | __STRING__
               : as2         @                        | as
               : coln        @                        | __NAME__
e              : dh          @                        | ,
1              : x4          @                        | )
               : x2          @                        | )


__DEF_PATH__    __FROM_PIVOT_1_2__
1              : frm         @ %__IF_KW__             | from
               : tab         @                        | __TABLE_NAME__
               : ssl         @                        + __SUB_SELECT__
               : pvt         @                        | pivot
               : x1          @                        | (
N              : fun         @                        | __NAME__        __//__ sum ....
               : fs          @                        | (
               : col1        @                        | __NAME__
               : fe          @                        | )
               : as1         @ %__IF_KW__ CAN_SKIP    | as
               : colas       @                        | __NAME__
e              : dh1         @                        | ,
1              : for         @ %__IF_KW__             | for
               : col2        @                        | __NAME__
               : in          @                        | in
               : x3          @                        | (
N              : col22       @                        | __NAME__
               : col23       @                        | =
               : val1        @                        | __INT__
               : val2        @                        + __STRING__
               : as2         @ CAN_SKIP               | as
               : coln        @                        | __NAME__
e              : dh          @                        | ,
1              : x4          @                        | )
               : x2          @                        | )
--------------------------------------------------------------------
1              : frm         @                        | from
               : tab         @                        | __TABLE_NAME__
               : ssl         @                        | __SUB_SELECT__
               : pvt         @                        | pivot
               : x1          @                        | (
N              : fun         @                        | __NAME__
               : fs          @                        | (
               : col1        @                        | __NAME__
               : fe          @                        | )
               : as1         @                        | as
               : colas       @                        | __NAME__
*              : col22       @                        | __NAME__
               : col23       @                        | =
               : val1        @                        | __INT__
               : val2        @                        | __STRING__
               : as2         @                        | as
               : coln        @                        | __NAME__
e              : coln        @                        | ,
1              : for         @                        | where
               : col2        @                        | __NAME__
               : in          @                        | in
               : x3          @                        | (
N              : val1        @                        | __INT__
               : val2        @                        | __STRING__
e              : dh          @                        | ,
1              : x4          @                        | )
1              : x2          @                        | )


__DEF_PATH__    __FROM_PIVOT_1_3__
1              : frm         @ %__IF_KW__             | from
               : tab         @                        | __TABLE_NAME__
               : ssl         @                        + __SUB_SELECT__
               : pvt         @                        | pivot
               : x1          @                        | (
N              : fun         @                        | __NAME__
               : fs          @                        | (
               : col1        @                        | __NAME__
               : fe          @                        | )
               : as1         @ %__IF_KW__ CAN_SKIP    | as
               : colas       @                        | __NAME__
               : col22       @                        | __NAME__
               : col23       @                        | =
               : val1        @                        | __INT__
               : val2        @                        + __STRING__
               : as2         @ %__IF_KW__ CAN_SKIP    | as
               : coln        @                        | __NAME__
e              : dh          @                        | ,
1              : for         @                        | where
               : col2        @                        | __NAME__
               : in          @                        | in
               : x3          @                        | (
N              : val3        @                        | __INT__
               : val4        @                        + __STRING__
e              : dh1         @                        | ,
1              : x4          @                        | )
               : x2          @                        | )
--------------------------------------------------------------------
1              : frm         @ STRING                 | from
               : pvt         @ STRING                 | (select ###,###,###
N              : fun         @                        | __NAME__
               : fs          @                        / (
               : col22       @ STRING                 \ case when
               : col22       @                        / __NAME__
               : col23       @                        / =
               : val1        @                        / __INT__
               : val2        @                        / __STRING__
               : col1        @                        / then
               : col1        @                        / __NAME__
               : col1        @ STRING                 / else null end
               : fe          @                        \ )
               : as1         @                        | as
               : coln        @                        | __NAME__
               : coln        @                        \ _
               : colas       @                        \ __NAME__
e              : dh          @                        | ,
1              : pvt         @                        | from
               : tab         @                        | __TABLE_NAME__
               : ssl         @                        | __SUB_SELECT__
1              : for         @                        | where
               : col2        @                        / __NAME__
               : in          @                        / in
               : x3          @                        \ (
N              : val3        @                        \ __INT__
               : val4        @                        \ __STRING__
e              : dh1         @                        \ ,
1              : x4          @                        \ )
               : x4          @ STRING                 | group by ###,###,###
               : x2          @                        | )


__DEF_SUB_PATH__       __TABLE_NAME__
1        : srctab           @               | __NAME__
+        : schema           @               | __NAME__
         : pp               @               | .
         : srctab2          @               | __NAME__


__DEF_SUB_PATH__   __SUB_SELECT__
1        : x1               @               | __SUB__


__DEF_PATH__   __SUB__
1        : x1               @               | ( 
N        : x2               @               | __ALL_STR__
         : x3               @               + __SUB__
1        : x4               @               | )


__DEF_STR__   __ALL_STR__
<1,20000>
[1,20000]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*-_+={}[]\|:;'"<,>.?/


__DEF_STR__   __NAME__
<1,100>
[1,1]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_??
[0,100]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_??
[NO] create insert update delete truncate drop merge table select inner left join on from where group order partition by having union all with as set between and or like in is not null case when then pivot lateral view 


__DEF_STR__   __FLOAT__
<1,100>
[1,50]0123456789
[1,1].
[1,50]0123456789


__DEF_STR__   __INT__
<1,100>
[1,100]0123456789


__DEF_SUB_PATH__   __STRING__
1       : x1                  | '
        : x2                  | __ANY__
        : x3                  | '


### 转换规则详细说明:

以上PIVOT函数的转换规则比较复杂,不能一次性转换完毕,这里分成3次转换完成:

ZGLanguage -e PIVOT_UNPIVOT_SQL_REPLACE.syn -r pivot_unpivot.code -o 1_mid_result.zgl
ZGLanguage -e PIVOT_UNPIVOT_SQL_REPLACE.syn -r 1_mid_result.zgl -o 2_mid_result.zgl
ZGLanguage -e PIVOT_UNPIVOT_SQL_REPLACE.syn -r 2_mid_result.zgl -o result.zgl


# 第1次转换规则 “__FROM_PIVOT_1_1__” 对源代码进行转换,完成 值“qtr” 和 枚举值 “Q1,Q2,Q3,Q4” 的一一映射关系,得到如下结果:

SELECT *
FROM (select country,state,yr,qtr,sales,cogs from table111) 
PIVOT
(
    SUM(sales ) AS ss1 ,
    SUM(cogs) AS sc
    FOR qtr IN
    (  
    qtr = 'Q1' AS Quarter1 ,  
    qtr = 'Q2' AS Quarter2 ,  
    qtr = 'Q3' AS Quarter3 ,  
    qtr = 'Q4' AS Quarter4
    )
) tmp
;


# 第2次转换规则 “__FROM_PIVOT_1_2__” 对 “__FROM_PIVOT_1_1__” 的转换结果(以上)再次进行转换。

 完成:

 (A) 聚合函数“SUM字段” 和 “qtr字段” 的笛卡尔积映射

 (B) FOR 结构转成 where 结构

 得到如下结果:

SELECT *
FROM (select country,state,yr,qtr,sales,cogs from table111) PIVOT
(
    SUM(sales) AS ss1   qtr = 'Q1' AS Quarter1 ,
    SUM(sales) AS ss1   qtr = 'Q2' AS Quarter2 ,
    SUM(sales) AS ss1   qtr = 'Q3' AS Quarter3 ,
    SUM(sales) AS ss1   qtr = 'Q4' AS Quarter4 ,
  
    SUM(cogs) AS sc     qtr = 'Q1' AS Quarter1 ,
    SUM(cogs) AS sc     qtr = 'Q2' AS Quarter2 ,
    SUM(cogs) AS sc     qtr = 'Q3' AS Quarter3 ,
    SUM(cogs) AS sc     qtr = 'Q4' AS Quarter4 
  
  where qtr IN
    (
        'Q1' ,
        'Q2' ,
        'Q3' ,
        'Q4'
    )
) tmp
;



# 第3次转换规则 “__FROM_PIVOT_1_3__” 对 “__FROM_PIVOT_1_2__” 的转换结果(以上)再次进行转换。

 完成:

 (A) 对SUM开头的字段内容进行新增、位移、合并等操作,形成语法正确的字段逻辑

 (B) 剔除PIVOT关键字,移动子查询到 where 语句上方

 (C) 新增待人工补充部分: select ###,###,###   group by ###,###,###

 得到最终结果:

SELECT *
FROM 
(
  select ###,###,###
         SUM(case when qtr='Q1' then sales else null end) AS Quarter1_ss1,
         SUM(case when qtr='Q2' then sales else null end) AS Quarter2_ss1,
         SUM(case when qtr='Q3' then sales else null end) AS Quarter3_ss1,
         SUM(case when qtr='Q4' then sales else null end) AS Quarter4_ss1,
         SUM(case when qtr='Q1' then cogs else null end) AS Quarter1_sc,
         SUM(case when qtr='Q2' then cogs else null end) AS Quarter2_sc,
         SUM(case when qtr='Q3' then cogs else null end) AS Quarter3_sc,
         SUM(case when qtr='Q4' then cogs else null end) AS Quarter4_sc
  from (select country,state,yr,qtr,sales,cogs from table111) 
 where qtr IN('Q1','Q2','Q3','Q4')
 group by ###,###,###
) tmp
;


### 新增待补充部分 ###,###,### 说明:

1、通过简单的配置,不能直接转换成完全可用的SQL代码,有些代码部分依然需要人工补充

2、需要人工补充的部分,已经通过 ###,###,### 明显地标注出来

3、通过工具已经完成了大部分的转换工作,极大的减轻了人工参与的工作量,规避人工修改失误的风险


源代码下载: https://gitee.com/zgl-20053779/zglanguage



相关文章
|
6天前
|
人工智能 自然语言处理 Shell
🦞 如何在 Moltbot 配置阿里云百炼 API
本教程指导用户在开源AI助手Clawdbot中集成阿里云百炼API,涵盖安装Clawdbot、获取百炼API Key、配置环境变量与模型参数、验证调用等完整流程,支持Qwen3-max thinking (Qwen3-Max-2026-01-23)/Qwen - Plus等主流模型,助力本地化智能自动化。
🦞 如何在 Moltbot 配置阿里云百炼 API
|
4天前
|
人工智能 JavaScript 应用服务中间件
零门槛部署本地AI助手:Windows系统Moltbot(Clawdbot)保姆级教程
Moltbot(原Clawdbot)是一款功能全面的智能体AI助手,不仅能通过聊天互动响应需求,还具备“动手”和“跑腿”能力——“手”可读写本地文件、执行代码、操控命令行,“脚”能联网搜索、访问网页并分析内容,“大脑”则可接入Qwen、OpenAI等云端API,或利用本地GPU运行模型。本教程专为Windows系统用户打造,从环境搭建到问题排查,详细拆解全流程,即使无技术基础也能顺利部署本地AI助理。
5632 13
|
10天前
|
人工智能 API 开发者
Claude Code 国内保姆级使用指南:实测 GLM-4.7 与 Claude Opus 4.5 全方案解
Claude Code是Anthropic推出的编程AI代理工具。2026年国内开发者可通过配置`ANTHROPIC_BASE_URL`实现本地化接入:①极速平替——用Qwen Code v0.5.0或GLM-4.7,毫秒响应,适合日常编码;②满血原版——经灵芽API中转调用Claude Opus 4.5,胜任复杂架构与深度推理。
7011 11
|
4天前
|
人工智能 JavaScript API
零门槛部署本地 AI 助手:Clawdbot/Meltbot 部署深度保姆级教程
Clawdbot(Moltbot)是一款智能体AI助手,具备“手”(读写文件、执行代码)、“脚”(联网搜索、分析网页)和“脑”(接入Qwen/OpenAI等API或本地GPU模型)。本指南详解Windows下从Node.js环境搭建、一键安装到Token配置的全流程,助你快速部署本地AI助理。(239字)
3502 19
|
2天前
|
人工智能 机器人 Linux
保姆级 OpenClaw (原 Clawdbot)飞书对接教程 手把手教你搭建 AI 助手
OpenClaw(原Clawdbot)是一款开源本地AI智能体,支持飞书等多平台对接。本教程手把手教你Linux下部署,实现数据私有、系统控制、网页浏览与代码编写,全程保姆级操作,240字内搞定专属AI助手搭建!
2763 7
保姆级 OpenClaw (原 Clawdbot)飞书对接教程 手把手教你搭建 AI 助手
|
5天前
|
人工智能 安全 Shell
在 Moltbot (Clawdbot) 里配置调用阿里云百炼 API 完整教程
Moltbot(原Clawdbot)是一款开源AI个人助手,支持通过自然语言控制设备、处理自动化任务,兼容Qwen、Claude、GPT等主流大语言模型。若需在Moltbot中调用阿里云百炼提供的模型能力(如通义千问3系列),需完成API配置、环境变量设置、配置文件编辑等步骤。本文将严格遵循原教程逻辑,用通俗易懂的语言拆解完整流程,涵盖前置条件、安装部署、API获取、配置验证等核心环节,确保不改变原意且无营销表述。
2121 6
|
5天前
|
机器人 API 数据安全/隐私保护
只需3步,无影云电脑一键部署Moltbot(Clawdbot)
本指南详解Moltbot(Clawdbot)部署全流程:一、购买无影云电脑Moltbot专属套餐(含2000核时);二、下载客户端并配置百炼API Key、钉钉APP KEY及QQ通道;三、验证钉钉/群聊交互。支持多端,7×24运行可关闭休眠。
3450 7
|
3天前
|
人工智能 JavaScript 安全
Clawdbot 对接飞书详细教程 手把手搭建你的专属 AI 助手
本教程手把手教你将 Moltbot(原 Clawdbot)部署在 Linux 服务器,并对接飞书打造专属 AI 助手:涵盖环境准备、Node.js/NVM 安装、Moltbot 快速安装(支持 Qwen 模型)、Web 管理面板配置及飞书应用创建、权限设置与事件回调对接,全程图文指引,安全可靠。
2210 3
Clawdbot 对接飞书详细教程 手把手搭建你的专属 AI 助手
|
5天前
|
存储 安全 数据库
使用 Docker 部署 Clawdbot(官方推荐方式)
Clawdbot 是一款开源、本地运行的个人AI助手,支持 WhatsApp、Telegram、Slack 等十余种通信渠道,兼容 macOS/iOS/Android,可渲染实时 Canvas 界面。本文提供基于 Docker Compose 的生产级部署指南,涵盖安全配置、持久化、备份、监控等关键运维实践(官方无预构建镜像,需源码本地构建)。
2426 7
|
5天前
|
人工智能 应用服务中间件 API
刚刚,阿里云上线Clawdbot全套云服务!
阿里云上线Moltbot(原Clawdbot)全套云服务,支持轻量服务器/无影云电脑一键部署,可调用百炼平台百余款千问模型,打通iMessage与钉钉消息通道,打造开箱即用的AI智能体助手。
2742 24
刚刚,阿里云上线Clawdbot全套云服务!