在低代码开发的大趋势下,如何快速搭建功能强大且灵活的 SQL 查询,以满足复杂多变的业务需求,成为开发者面临的关键挑战。为此,我们精心研发了一款 SQL 查询生成器,它凭借高度灵活和便捷易用的特性,助力开发者在低代码环境中高效完成数据查询工作,大幅提升开发效率。
支持SQL表达式、聚合函数,如SUM(求和)、COUNT(计数)等计算。借助这些函数,开发者能够轻松对数据进行统计分析,像计算订单总金额、统计用户数量等操作,都能快速完成,让数据洞察变得轻而易举。
实现GROUP BY语句,方便对数据进行分组分析。可以依据不同维度对数据进行分组,比如按用户分组统计每个用户的订单数量,或者按日期分组统计每日的销售额,帮助开发者从多个角度深入理解数据。
不仅支持ASC(升序)、DESC(降序)排序,还允许定义多级排序优先级。开发者可根据业务需求,灵活地对查询结果进行排序,确保展示的数据符合业务逻辑,让数据呈现更加清晰有序。
支持多表关联,并能灵活设置连接条件。无论是简单的内连接,还是复杂的左连接、右连接,都能轻松实现,满足复杂业务场景下的数据关联查询需求,帮助开发者从海量数据中挖掘出关键信息。
通过LIMIT和OFFSET实现高效的数据分页。在处理大量数据时,分页功能可以有效提升查询性能,减少数据传输量,提高用户体验,让数据处理不再卡顿。
在 SQL 查询生成器的底层架构中,Field 类与 TableQuery 类分别扮演着基础支撑与核心驱动的关键角色。这两个类紧密协作、深度交互,共同构建起一个能够满足低代码开发中复杂 SQL 查询需求的高效体系。
Field 类作为整个查询生成器的基础模块,用于精准表示 SQL 查询中的字段,为后续的各种操作奠定坚实基础。
class Field {
constructor(name, alias = null, expression = null) {
this.name = name; // 字段名
this.alias = alias; // 字段别名
this.expression = expression; // 聚合函数,如SUM、COUNT
this.sortDirection = null; // 排序方向ASC或DESC
this.sortPriority = null; // 排序优先级
this.isGrouped = false; // 分组标记
}
// 设置聚合表达式
setExpression(expression) {
this.expression = expression;
return this;
}
// 启用分组
groupBy() {
this.isGrouped = true;
return this;
}
// 定义排序规则
setSort(direction, priority = null) {
this.sortDirection = direction.toUpperCase();
this.sortPriority = priority;
return this;
}
// 生成SQL字符串
toSQL(tableAlias = null) {
let sql = this.expression
? `${this.expression}(${tableAlias? `${tableAlias}.${this.name}` : this.name})`
: tableAlias
? `${tableAlias}.${this.name}`
: this.name;
if (this.alias) {
sql += ` AS ${this.alias}`;
}
return sql;
}
// 返回排序规则的SQL表达式
toSortSQL(tableAlias = null) {
if (!this.sortDirection) return null;
const sql = this.expression
? `${this.expression}(${tableAlias? `${tableAlias}.${this.name}` : this.name})`
: this.toSQL(tableAlias);
return `${sql} ${this.sortDirection}`;
}
}
通过一系列丰富的方法,Field 类实现了灵活的字段操作。开发者借助setExpression方法轻松设置SUM、COUNT等聚合函数,利用groupBy方法开启分组,通过setSort方法定义排序规则,还可通过toSQL和toSortSQL方法生成 SQL 字符串和排序规则的 SQL 表达式,方便与数据库进行交互。
TableQuery 类是 SQL 查询生成器的核心部分,在 Field 类的基础上,通过提供表抽象和多表管理接口,极大地简化了 SQL 语句的编写过程,尤其适用于低代码开发中的复杂查询场景。
class TableQuery {
constructor(name = null, alias = null) {
this.name = name; // 表名
this.alias = alias || name; // 表别名
this.fields = []; // 查询字段
this.joins = []; // 连接表
this.filters = []; // 条件过滤
this.pagination = { limit: null, offset: null }; // 分页设置
this.joinType = null; // 当前表连接类型
this.joinCondition = null; // 连接条件
}
// 添加字段
addField(name, alias = null, expression = null) {
const field = new Field(name, alias, expression);
this.fields.push(field);
return field;
}
// 设置连接类型与条件
setJoin(type, condition) {
this.joinType = type.toUpperCase();
if (Array.isArray(condition)) {
this.joinCondition = condition.map((cond) => `(${cond})`).join(" AND ");
} else {
this.joinCondition = condition;
}
return this;
}
// 添加连接表
addJoin(tableQuery) {
this.joins.push(tableQuery);
return this;
}
// 增加过滤条件
addFilter(field, operator, value) {
this.filters.push({ field, operator, value });
return this;
}
// 设置分页
setPagination(limit, offset = 0) {
this.pagination = { limit, offset };
return this;
}
// 生成SQL查询语句
toSQL() {
const selectClause = this.fields.map((field) => field.toSQL()).join(", ");
const fromClause = this.joins
.map((join) => `${join.joinType} JOIN ${join.toSQL()} ON ${join.joinCondition}`)
.join(" ");
const whereClause = this.filters
.map((filter) => `${filter.field} ${filter.operator} '${filter.value}'`)
.join(" AND ");
const groupByClause = this.fields
.filter((field) => field.isGrouped)
.map((field) => field.name)
.join(", ");
const groupBy = groupByClause? `GROUP BY ${groupByClause}` : "";
const orderByClause = this.fields
.filter((field) => field.sortDirection)
.sort((a, b) => (a.sortPriority || Infinity) - (b.sortPriority || Infinity))
.map((field) => field.toSortSQL())
.join(", ");
const orderBy = orderByClause? `ORDER BY ${orderByClause}` : "";
const limitClause = this.pagination.limit? `LIMIT ${this.pagination.limit}` : "";
const offsetClause = this.pagination.offset? `OFFSET ${this.pagination.offset}` : "";
return `
SELECT ${selectClause}
${fromClause? `FROM ${fromClause}` : ""}
${whereClause? `WHERE ${whereClause}` : ""}
${groupBy}
${orderBy}
${limitClause}
${offsetClause}
`.trim();
}
}
在 TableQuery 类中,addField方法用于添加由 Field 类实例化的字段,从而实现对查询字段的定义和操作。setJoin方法支持设置INNER JOIN、LEFT JOIN等多种连接类型与条件,满足不同业务场景下的多表关联需求 。addJoin方法实现了连接表的添加,进一步拓展查询的范围。addFilter和setPagination方法则分别用于增加过滤条件和设置分页,实现动态条件筛选和高效分页。通过内置的多层逻辑,TableQuery 类最终能够自动拼接生成完整的 SQL 查询语句,大大减少了开发者手动编写 SQL 的工作量。
Field 类和 TableQuery 类相互配合,从基础字段操作到复杂多表查询构建,共同为低代码平台的开发者提供了强大且灵活的 SQL 查询生成能力。
此示例展示了如何统计每位用户的总金额,并按用户分组,理想应用于低代码平台的数据展示模块中。
const ordersTable = new TableQuery("orders", "o");
ordersTable
.addField("o.user_id", "user_id").groupBy()
.addField("SUM(o.amount)", "total_amount").setExpression("SUM").setSort("DESC", 1)
.addField("COUNT(o.id)", "order_count").setExpression("COUNT")
.addFilter("o.status", "=", "completed")
.setPagination(10, 0);
console.log(ordersTable.toSQL());
以下代码生成了多表连接查询,可实现嵌套子查询,应用于复杂的数据分析场景。
const subquery = new TableQuery(null, "order_summary");
subquery
.addField("o.user_id", "user_id").groupBy()
.addField("SUM(o.amount)", "total_amount").setExpression("SUM")
.addField("COUNT(o.id)", "order_count").setExpression("COUNT");
const ordersTable = new TableQuery("orders", "o");
ordersTable
.addField("o.user_id", "user_id")
.addJoin(subquery);
console.log(ordersTable.toSQL());
通过模块化的 Field 和 TableQuery 类设计,我们成功构建了一款适用于低代码平台的 SQL 查询生成器。它以简化开发流程、提高生产效率为目标,为低代码平台开发者提供了强大的数据查询支持。
相信在不断的优化和完善下,这款工具将成为低代码平台开发者实现高效数据查询的不二之选,助力低代码开发迈向新的高度,开启数据查询的全新篇章。