结论
用 timeDimensions 做时间分桶的 analytics 查询,SQL 正确地 SELECT 了分桶列,但响应把它丢了 —— rows 里只剩度量值,fields 也不声明该维度。用 dimensions 传字符串维度则正常返回。趋势图拿到 N 个柱子却没有任何 x 轴标签。
dogfood 真实运行 app(showcase,SQLite)实测发现,非静态分析。
复现
POST /api/v1/analytics/query
{"cube":"showcase_delivery","measures":["count"],
"timeDimensions":[{"dimension":"due_date","granularity":"month"}]}
响应:
{"success": true, "data": {
"rows": [{"count": 2}, {"count": 8}],
"fields": [{"name": "count", "type": "number"}],
"sql": "SELECT date_trunc('month', due_date) AS \"due_date\", COUNT(*) AS \"count\" FROM \"showcase_task\" GROUP BY date_trunc('month', due_date)"
}}sql 字段自证:分桶列被 SELECT 了且带 AS \"due_date\" 别名,只是没进 rows/fields。
对照组(同一 cube,改用字符串维度)完全正常:
{"cube":"showcase_delivery","measures":["count"],"dimensions":["priority"]}
→ rows: [{"priority":"high","count":3}, {"priority":"low","count":1},
{"priority":"medium","count":4}, {"priority":"urgent","count":2}]
fields: [{"name":"priority","type":"string"}, {"name":"count","type":"number"}]
所以不是「分组没生效」(分组是对的,2+8=10=全量),是投影/字段声明只覆盖了 dimensions,漏了 timeDimensions。
影响
任何用 timeDimensions 的趋势图/时间序列 widget:数据点数量和数值都对,但每个点没有时间标签。前端要么渲染出无标签的柱子,要么只能靠数组下标猜时间 —— 后者在有空桶时会错位。
定位线索
packages/services/service-analytics/src/analytics-service.ts 约 961 行:ad-hoc cube 合成时 timeDimensions 确实被登记进了 dimensions map(type: 'time'),所以 SQL 编译拿得到它。漏的应该在结果投影/fields 推导那一段 —— 它似乎只枚举 query.dimensions,没有把 query.timeDimensions 并进去。(未深挖,留给修复者确认。)
与 temporal 线的关系
不是#3912/#3994/#4022 这条线引入的:字符串维度走同一条投影路径且正常,说明问题在 timeDimensions 的字段枚举,与存储形态无关。但它落在同一域内,且正是「后端数据对、前端看不到」的那类问题,所以单独记录而不是并入已合并的 PR。
顺带确认(都正常)
同轮 dogfood 验证的其余项全部通过,一并记录以免误伤:dateRange 窗口过滤判别性正确(宽窗口=全量 10 行,2010 空窗口=0 行)、走的是 native-SQL 分支(date_trunc + $1/$2 绑定,即 #3979 契约钩子那条缝)。
结论
用
timeDimensions做时间分桶的 analytics 查询,SQL 正确地 SELECT 了分桶列,但响应把它丢了 ——rows里只剩度量值,fields也不声明该维度。用dimensions传字符串维度则正常返回。趋势图拿到 N 个柱子却没有任何 x 轴标签。dogfood 真实运行 app(showcase,SQLite)实测发现,非静态分析。
复现
响应:
{"success": true, "data": { "rows": [{"count": 2}, {"count": 8}], "fields": [{"name": "count", "type": "number"}], "sql": "SELECT date_trunc('month', due_date) AS \"due_date\", COUNT(*) AS \"count\" FROM \"showcase_task\" GROUP BY date_trunc('month', due_date)" }}sql字段自证:分桶列被 SELECT 了且带AS \"due_date\"别名,只是没进rows/fields。对照组(同一 cube,改用字符串维度)完全正常:
所以不是「分组没生效」(分组是对的,2+8=10=全量),是投影/字段声明只覆盖了
dimensions,漏了timeDimensions。影响
任何用
timeDimensions的趋势图/时间序列 widget:数据点数量和数值都对,但每个点没有时间标签。前端要么渲染出无标签的柱子,要么只能靠数组下标猜时间 —— 后者在有空桶时会错位。定位线索
packages/services/service-analytics/src/analytics-service.ts约 961 行:ad-hoc cube 合成时timeDimensions确实被登记进了dimensionsmap(type: 'time'),所以 SQL 编译拿得到它。漏的应该在结果投影/fields推导那一段 —— 它似乎只枚举query.dimensions,没有把query.timeDimensions并进去。(未深挖,留给修复者确认。)与 temporal 线的关系
不是#3912/#3994/#4022 这条线引入的:字符串维度走同一条投影路径且正常,说明问题在
timeDimensions的字段枚举,与存储形态无关。但它落在同一域内,且正是「后端数据对、前端看不到」的那类问题,所以单独记录而不是并入已合并的 PR。顺带确认(都正常)
同轮 dogfood 验证的其余项全部通过,一并记录以免误伤:
dateRange窗口过滤判别性正确(宽窗口=全量 10 行,2010 空窗口=0 行)、走的是 native-SQL 分支(date_trunc+$1/$2绑定,即 #3979 契约钩子那条缝)。