GraphQL查询计算时间戳差值报错,求SQL转GraphQL方案及类型转换方法
解决方案:GraphQL时间戳差值计算与类型转换问题
一、错误原因解析
你遇到的Error: Invalid number, expected digit but got: "U"是因为GraphQL查询语法不支持直接在字段名位置做算术运算,JobStartDateTime-UpUpdateDateTime这种写法完全不符合GraphQL规范,而且你还写错了字段名(应为UpdateDateTime而非UpUpdateDateTime)。
二、实现SQL中AvgTime逻辑的两种方式
方式1:后端Schema新增自定义字段(推荐)
GraphQL是Schema驱动的,这类聚合计算、字段推导逻辑最好放在后端实现:
- 在你的GraphQL Schema中新增
AvgTime字段(类型设为Int) - 在Resolver(解析器)中实现对应计算逻辑,还原SQL里
ROUND(avg(timestampdiff(SECOND, JobStartDateTime, UpdateDateTime)),0)的逻辑
示例Resolver伪代码(以JavaScript为例):
const resolvers = { Query: { MyQuery: async (parent, args, context) => { // 直接在数据库查询中完成计算,返回包含AvgTime的结果 const result = await context.db.query(` SELECT Region, JobStartDateTime, UpdateDateTime, ROUND(avg(timestampdiff(SECOND, JobStartDateTime, UpdateDateTime)),0) as AvgTime FROM your_table GROUP BY Region, JobStartDateTime, UpdateDateTime `); return result; } } };
修改后即可直接在查询中请求该字段:
query MyQuery { MyQuery { Region JobStartDateTime UpdateDateTime AvgTime } }
方式2:客户端侧计算(仅适合单条数据差值)
如果无法修改后端Schema,可以在客户端获取原始时间字段后自行计算,但这种方式无法实现SQL中的avg()聚合逻辑:
- 先查询原始字段:
query MyQuery { MyQuery { Region JobStartDateTime UpdateDateTime } }
- 在客户端代码中计算单条数据的时间差(以JavaScript为例):
// 假设返回的时间为ISO格式字符串 const calculateTimeDiff = (data) => { return data.map(item => { const start = new Date(item.JobStartDateTime).getTime(); const end = new Date(item.UpdateDateTime).getTime(); const diffSeconds = Math.round((end - start) / 1000); return { ...item, AvgTime: diffSeconds }; }); };
三、关于时间差转DateTime类型的说明
时间差的秒数是代表时间段的数字,无法直接转为DateTime类型(DateTime指代具体时间点而非时间段),但可以将秒数转换为人类可读的时间段格式(如HH:mm:ss):
后端转换示例(SQL)
直接在查询中返回格式化后的字符串:
SELECT ROUND(avg(timestampdiff(SECOND, JobStartDateTime, UpdateDateTime)),0) as AvgTimeSeconds, SEC_TO_TIME(ROUND(avg(timestampdiff(SECOND, JobStartDateTime, UpdateDateTime)),0)) as AvgTimeFormatted FROM your_table
客户端转换示例(JavaScript)
const formatSecondsToTime = (seconds) => { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const secs = seconds % 60; return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; };
内容的提问来源于stack exchange,提问作者ashish bandiwar
相关产品推荐
相关产品推荐

