diff --git a/README.md b/README.md
index e07c7a9..adeb856 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,8 @@ from
当然,以上只是一个示例,真实大数据离线分析的场景下,SQL 可比这复杂 N 倍!
+如果感兴趣的话,欢迎往下看文档,还有更复杂的示例~
+
## 优势
1. 支持在线编辑 JSON 和 SQL,支持代码高亮、语法校验、一键格式化、查找和替换、代码块折叠等,体验良好
@@ -99,6 +101,72 @@ from
`@xxx(yy = 1 ||| zz = #{变量})`:引用其他 SQL,可传参,参数可再用变量来表示,使用 |||(三个竖线)来分隔参数。
+## 复杂示例
+
+需求:用一句 SQL 查询出以下表格
+
+![](./doc/assets/complex-example.png)
+
+这个表格的难点在哪?
+
+1. 查汇总和查明细的粒度不同,不能用 group by 区分,只能用 union(红色)
+2. 分类列中不同行的数据有交叉,不能用 group by 区分,只能用 union(
+3. 每一列由多张表共同 join 而成,且不同分类可关联的表不同,须进行区分(灰色表示无法关联),并将缺失的字段补齐(否则无法 union)
+4. 不同行的同一列计算公式可能不同(蓝色)
+5. 不同列的过滤条件不同(比如最后两列墨绿色是要查全校,其余列只查 1 年级)
+6. 要查询同环比,只能用 2 份完整的数据去 join 然后错位计算来得出
+
+显然,这个表中很多查询逻辑是重复但又不同的。
+
+这么算下来,最后这个 SQL 中到底会包含多少个基础表的 select 呢?每个基础表查询要重复编写多少遍呢?
+
+然而,这个表格也只是鱼皮对实际需求简化后才得来的,实际需求比这还复杂几倍!
+
+可想而知,人工写有多恶心?!
+
+但是使用本工具,只需编写如下结构化的 JSON:
+
+```json
+{
+ "main": "select (a / b - 1) from (@查整体(date = 今天)) a, (@查整体(date = 昨天)) b",
+ "查整体": "@查年级() union @查1班() union @查2班() where date = #{date}",
+ "查年级": "@查汇总_性别汇总() union @查汇总_性别分组() union @查汇总_爱好汇总() union @查汇总_爱好分组() union @查汇总_电脑类别汇总() union @查汇总_电脑类别分组()",
+ "查汇总_性别汇总": "@查除电脑关联表()",
+ "查汇总_性别分组": "@查除电脑关联表() group by 性别",
+ "查汇总_爱好汇总": "@查除电脑关联表()",
+ "查汇总_爱好分组": "@查除电脑关联表() where 爱好 in (xx) group by 爱好",
+ "查汇总_电脑类别汇总": "@查除三连和学习表()",
+ "查汇总_电脑类别分组": "@查除三连和学习表() group by 电脑类别",
+
+ "查1班": "@查1班_性别汇总() union @查1班_性别分组() union @查1班_爱好汇总() union @查1班_爱好分组() union @查1班_电脑类别汇总() union @查汇总_电脑类别分组()",
+ "查1班_性别汇总": "@查除电脑关联表() where 1班",
+ "查1班_性别分组": "@查除电脑关联表() where 1班 group by 性别",
+ "查1班_爱好汇总": "@查除电脑关联表() where 1班",
+ "查1班_爱好分组": "@查除电脑关联表() where 1班 and 爱好 in (xx) group by 爱好",
+ "查1班_电脑类别汇总": "@查除三连和学习表() where 1班",
+ "查1班_电脑类别分组": "@查除三连和学习表() where 1班 group by 电脑类别",
+
+ "查2班": "@查2班_性别汇总() union @查2班_性别分组() union @查2班_电脑类别汇总() union @查2班_电脑类别分组()",
+ "查2班_性别汇总": "@查除电脑关联表() where 2班",
+ "查2班_性别分组": "@查除电脑关联表() where 2班 group by 性别",
+ "查2班_电脑类别汇总": "@查除三连和学习表() where 2班",
+ "查2班_电脑类别分组": "@查除三连和学习表() where 2班 group by 电脑类别",
+
+ "查所有关联表": "@查信息表() left join (@查三连表()) left join (@查学习表()) left join (@查电脑表()) left join (@查全校信息())",
+ "查除电脑关联表": "@查信息表() left join (@查三连表()) left join (@查学习表()) left join (@查全校信息())",
+ "查除三连和学习表": "@查信息表() left join (@查电脑表()) left join (@查全校信息())",
+ "查信息表": "select 字段 from 信息表 where 年级 = 1",
+ "查三连表": "select 字段 from 三连表 where 年级 = 1",
+ "查学习表": "select 字段 from 学习表 where 年级 = 1",
+ "查电脑表": "select 字段 from 电脑表 where 年级 = 1",
+ "查全校信息": "select 字段 from 信息表"
+}
+```
+
+就能自动生成 SQL 了,还可以查看调用关系,非常清晰:
+
+![](./doc/assets/complex-example-result.png)
+
## 实现
diff --git a/doc/assets/complex-example-result.png b/doc/assets/complex-example-result.png
new file mode 100644
index 0000000..935a6a1
Binary files /dev/null and b/doc/assets/complex-example-result.png differ
diff --git a/doc/assets/complex-example.png b/doc/assets/complex-example.png
new file mode 100644
index 0000000..c8018e7
Binary files /dev/null and b/doc/assets/complex-example.png differ
diff --git a/src/App.vue b/src/App.vue
index 4e226d4..0c92a3a 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -59,6 +59,14 @@ const getSQL = () => {
console.log(invokeTree.value);
};
+const importExampleAndCal = () => {
+ if (inputEditor.value) {
+ const exampleJSON = importExample("complex");
+ toRaw(inputEditor.value).setValue(exampleJSON);
+ inputEditor.value.getAction("editor.action.formatDocument").run();
+ }
+};
+
const showInvokeTree = () => {
if (!invokeTree.value) {
getSQL();
@@ -121,7 +129,7 @@ onMounted(() => {
查看调用树
-
+
导入例子
diff --git a/src/examples/complex.json b/src/examples/complex.json
new file mode 100644
index 0000000..e043ab0
--- /dev/null
+++ b/src/examples/complex.json
@@ -0,0 +1,31 @@
+{
+ "main": "select (a / b - 1) from (@查整体(date = 今天)) a, (@查整体(date = 昨天)) b",
+ "查整体": "@查年级() union @查1班() union @查2班() where date = #{date}",
+ "查年级": "@查汇总_性别汇总() union @查汇总_性别分组() union @查汇总_爱好汇总() union @查汇总_爱好分组() union @查汇总_电脑类别汇总() union @查汇总_电脑类别分组()",
+ "查汇总_性别汇总": "@查除电脑关联表()",
+ "查汇总_性别分组": "@查除电脑关联表() group by 性别",
+ "查汇总_爱好汇总": "@查除电脑关联表()",
+ "查汇总_爱好分组": "@查除电脑关联表() where 爱好 in (xx) group by 爱好",
+ "查汇总_电脑类别汇总": "@查除三连和学习表()",
+ "查汇总_电脑类别分组": "@查除三连和学习表() group by 电脑类别",
+ "查1班": "@查1班_性别汇总() union @查1班_性别分组() union @查1班_爱好汇总() union @查1班_爱好分组() union @查1班_电脑类别汇总() union @查汇总_电脑类别分组()",
+ "查1班_性别汇总": "@查除电脑关联表() where 1班",
+ "查1班_性别分组": "@查除电脑关联表() where 1班 group by 性别",
+ "查1班_爱好汇总": "@查除电脑关联表() where 1班",
+ "查1班_爱好分组": "@查除电脑关联表() where 1班 and 爱好 in (xx) group by 爱好",
+ "查1班_电脑类别汇总": "@查除三连和学习表() where 1班",
+ "查1班_电脑类别分组": "@查除三连和学习表() where 1班 group by 电脑类别",
+ "查2班": "@查2班_性别汇总() union @查2班_性别分组() union @查2班_电脑类别汇总() union @查2班_电脑类别分组()",
+ "查2班_性别汇总": "@查除电脑关联表() where 2班",
+ "查2班_性别分组": "@查除电脑关联表() where 2班 group by 性别",
+ "查2班_电脑类别汇总": "@查除三连和学习表() where 2班",
+ "查2班_电脑类别分组": "@查除三连和学习表() where 2班 group by 电脑类别",
+ "查所有关联表": "@查信息表() left join (@查三连表()) left join (@查学习表()) left join (@查电脑表()) left join (@查全校信息())",
+ "查除电脑关联表": "@查信息表() left join (@查三连表()) left join (@查学习表()) left join (@查全校信息())",
+ "查除三连和学习表": "@查信息表() left join (@查电脑表()) left join (@查全校信息())",
+ "查信息表": "select 字段 from 信息表 where 年级 = 1",
+ "查三连表": "select 字段 from 三连表 where 年级 = 1",
+ "查学习表": "select 字段 from 学习表 where 年级 = 1",
+ "查电脑表": "select 字段 from 电脑表 where 年级 = 1",
+ "查全校信息": "select 字段 from 信息表"
+}
\ No newline at end of file
diff --git a/src/examples/index.ts b/src/examples/index.ts
index 4c25e74..262305f 100644
--- a/src/examples/index.ts
+++ b/src/examples/index.ts
@@ -1,7 +1,9 @@
import init from "./init.json";
+import complex from "./complex.json";
const exampleMap: Record = {
init,
+ complex,
};
export const importExample = (key: string) => {
diff --git a/src/generator/index.ts b/src/generator/index.ts
index 5f88c38..aa0f9f0 100644
--- a/src/generator/index.ts
+++ b/src/generator/index.ts
@@ -92,6 +92,9 @@ function replaceParams(
}
// 动态、静态参数结合,且优先用静态参数
params = { ...(params ?? {}), ...currentNode.params };
+ if (invokeTreeNode) {
+ invokeTreeNode.params = params;
+ }
// 无需替换
if (!params || Object.keys(params).length < 1) {
return sql;