引言
在数据驱动的业务场景中,将业务需求快速转化为SQL查询是常见需求。本文将通过一个轻量级的sql_json_to_sql
函数,展示如何将JSON格式的查询描述转换为标准SQL语句,并结合实际业务场景验证其功能。
核心代码解析
1. 代码实现
def sql_json_to_sql(sql_json):
"""
将扩展后的 sql_json 转换为完整的 SQL 语句
:param sql_json: 生成的 sql_json 字典
:return: 对应的 SQL 语句字符串
"""
sql = []
# 构建基础 SELECT 和 FROM
select_clause = f"SELECT {', '.join(sql_json['select'])}"
from_clause = f"FROM {sql_json['from']}"
sql.append(select_clause)
sql.append(from_clause)
# 处理 JOIN
if sql_json.get("joins"):
join_clauses = []
for join in sql_json["joins"]:
join_type = join["type"].upper()
table = join["table"]
on_cond = join["on"]
join_clauses.append(f"{join_type} JOIN {table} ON {on_cond}")
sql.append(' '.join(join_clauses))
# 处理 WHERE 条件
if sql_json.get("conds"):
where_conditions = []
for cond in sql_json["conds"]:
field, op, value = cond
if isinstance(value, str) and not value.isdigit():
value = f"'{value}'"
where_conditions.append(f"{field} {op} {value}")
if where_conditions:
sql.append(f"WHERE {' AND '.join(where_conditions)}")
# 处理 GROUP BY 和 HAVING
if sql_json.get("group_by"):
sql.append(f"GROUP BY {', '.join(sql_json['group_by'])}")
if sql_json.get("having"):
sql.append(f"HAVING {' AND '.join(sql_json['having'])}")
# 处理 ORDER BY
if sql_json.get("order_by"):
order_expressions = [' '.join(ob) for ob in sql_json["order_by"]]
sql.append(f"ORDER BY {', '.join(order_expressions)}")
# 处理 LIMIT
if sql_json.get("limit"):
sql.append(f"LIMIT {sql_json['limit']}")
return ' '.join([s for s in sql if s]).strip()
2. 核心功能
- 基础查询:
SELECT
,FROM
- 联接操作:支持
INNER JOIN
、LEFT JOIN
等 - 条件过滤:
WHERE
条件组合(AND
) - 聚合与分组:
GROUP BY
+HAVING
- 排序与分页:
ORDER BY
+LIMIT
测试案例与业务场景
案例1:销售分析 - 筛选高销量车系
业务场景
销售团队需要快速查看2024年各车系销量排名,辅助销售策略制定。
输入JSON
{
"select": ["车系", "销量"],
"conds": [["年", "==", "2024"]],
"from": "即席查询",
"order_by": [["销量", "DESC"]],
"limit": 10
}
输出SQL
SELECT 车系, 销量
FROM 即席查询
WHERE 年 == '2024'
ORDER BY 销量 DESC
LIMIT 10
表结构
字段名 | 类型 | 说明 |
---|---|---|
车系 | VARCHAR(50) | 车系名称(如“SUV”) |
销量 | INT | 年度销量数值 |
年 | VARCHAR(4) | 销售年份(如“2024”) |
案例2:员工信息报告 - 跨表聚合
业务场景
HR部门需要生成各部门员工信息报告,按部门分组并排序。
输入JSON
{
"select": ["部门", "JSON_OBJECTAGG(员工ID, 姓名) AS 员工信息"],
"from": "员工表",
"joins": [
{"type": "INNER JOIN", "table": "部门表", "on": "员工表.部门ID = 部门表.ID"}
],
"group_by": ["部门"],
"order_by": [["部门", "ASC"]],
"limit": 5
}
输出SQL
SELECT 部门, JSON_OBJECTAGG(员工ID, 姓名) AS 员工信息
FROM 员工表
INNER JOIN 部门表 ON 员工表.部门ID = 部门表.ID
GROUP BY 部门
ORDER BY 部门 ASC
LIMIT 5
表结构
-
员工表
字段名 类型 说明 员工ID VARCHAR(20) 员工唯一标识 姓名 VARCHAR(50) 员工姓名 部门ID VARCHAR(20) 所属部门的外键 -
部门表
字段名 类型 说明 ID VARCHAR(20) 部门唯一标识(主键) 部门 VARCHAR(50) 部门名称(如“销售部”)
案例3:日志分析 - JSON路径查询
业务场景
运维团队分析系统日志中的错误级别分布,定位高频问题。
输入JSON
{
"select": ["JSON_VALUE(log, '$.severity') AS severity_level", "COUNT(*) AS log_count"],
"from": "WebSite.Logs",
"conds": [["JSON_VALUE(log, '$.severity')", "==", "P4"]],
"group_by": ["severity_level"],
"order_by": [["log_count", "DESC"]],
"limit": 10
}
输出SQL
SELECT JSON_VALUE(log, '$.severity') AS severity_level, COUNT(*) AS log_count
FROM WebSite.Logs
WHERE JSON_VALUE(log, '$.severity') == 'P4'
GROUP BY severity_level
ORDER BY log_count DESC
LIMIT 10
表结构
字段名 | 类型 | 说明 |
---|---|---|
log | JSON | 日志内容(如 {"severity": "P4", "message": "..."} ) |
案例4:订单分析 - 复合条件与分组过滤
业务场景
财务部门分析2024年非西藏地区高销售额订单,排除边缘地区。
输入JSON
{
"select": ["订单ID", "SUM(金额) AS 总销售额"],
"from": "订单表",
"conds": [["年份", "==", "2024"], ["省份", "!=", "西藏"]],
"group_by": ["订单ID"],
"having": ["总销售额 > 10000"],
"order_by": [["总销售额", "DESC"], ["订单ID", "ASC"]],
"limit": 20
}
输出SQL
SELECT 订单ID, SUM(金额) AS 总销售额
FROM 订单表
WHERE 年份 == '2024' AND 省份 != '西藏'
GROUP BY 订单ID
HAVING 总销售额 > 10000
ORDER BY 总销售额 DESC, 订单ID ASC
LIMIT 20
表结构
字段名 | 类型 | 说明 |
---|---|---|
订单ID | VARCHAR(20) | 订单唯一标识 |
金额 | DECIMAL(10,2) | 订单总金额 |
年份 | VARCHAR(4) | 订单年份(如“2024”) |
省份 | VARCHAR(20) | 订单所属省份 |
案例5:产品分析 - 聚合与HAVING过滤
业务场景
产品团队分析高价位产品类别,定位高端市场。
输入JSON
{
"select": ["产品类别", "AVG(价格) AS 平均价格"],
"from": "产品表",
"group_by": ["产品类别"],
"having": ["AVG(价格) > 1000"],
"order_by": [["平均价格", "ASC"]]
}
输出SQL
SELECT 产品类别, AVG(价格) AS 平均价格
FROM 产品表
GROUP BY 产品类别
HAVING AVG(价格) > 1000
ORDER BY 平均价格 ASC
表结构
字段名 | 类型 | 说明 |
---|---|---|
产品ID | VARCHAR(20) | 产品唯一标识 |
产品类别 | VARCHAR(50) | 产品分类(如“电子产品”) |
价格 | DECIMAL(10,2) | 产品单价 |
扩展性与局限性
-
支持场景
- 基础查询:SELECT、WHERE、ORDER BY、LIMIT
- 复杂查询:JOIN、GROUP BY、HAVING、JSON函数
- 多条件组合:AND 条件自动拼接
-
未来扩展方向
- DML支持:INSERT、UPDATE、DELETE
- 数据库适配:支持不同数据库的方言(如MySQL、PostgreSQL)
- 参数化查询:防止SQL注入,支持预编译语句
总结
通过将JSON描述转换为SQL语句,可以快速将业务需求转化为可执行的查询,提升开发效率。本文提供的工具和案例覆盖了销售分析、日志监控、订单统计等典型场景,帮助开发者在实际业务中灵活应用。