Firebird 2.5.9按半小时分组统计欧元金额的SQL查询问题
解决方案:Firebird 2.5.9按半小时间隔统计欧元总额
由于无法修改数据库结构,我们可以通过现有字符类型的时间字段构造半小时间隔分组键,以下提供两种可行的SQL写法:
方法一:直接基于时分字符字段计算分组
这种方式不需要构造完整时间戳,直接通过判断分钟数归属来生成半小时间隔标识:
SELECT Table1.Day AS TheDay, -- 生成半小时间隔标签(如08:00、08:30) CASE WHEN CAST(Table1.MI AS INTEGER) < 30 THEN LPAD(Table1.HH, 2, '0') || ':00' ELSE LPAD(Table1.HH, 2, '0') || ':30' END AS HalfHourInterval, SUM(Table2.Euro) AS EURO FROM Table1 INNER JOIN Table2 ON Table2.NUMOP = Table1.NUMOP WHERE Table1.DAY = '2024-08-31' GROUP BY TABLE1.DAY, CASE WHEN CAST(Table1.MI AS INTEGER) < 30 THEN LPAD(Table1.HH, 2, '0') || ':00' ELSE LPAD(Table1.HH, 2, '0') || ':30' END
说明:
- 使用
CAST(Table1.MI AS INTEGER)将字符型分钟转为数字,判断是否小于30来决定归属到当前小时的整点还是半点区间 LPAD(Table1.HH, 2, '0')确保小时数统一为两位格式(如8转为08)- Firebird 2.5不支持在
GROUP BY中直接使用SELECT别名,因此需要重复CASE表达式
方法二:构造时间戳后按半小时截断分组
如果需要更精准的时间处理(比如跨小时的边界场景),可以先拼接完整时间戳再截断到半小时:
SELECT Table1.Day AS TheDay, -- 截断到最近的半小时起始时间(如08:15转为08:00,08:35转为08:30) DATEADD( MINUTE, -(EXTRACT(MINUTE FROM CAST(FullTimestamp AS TIMESTAMP)) % 30), CAST(FullTimestamp AS TIMESTAMP) ) AS HalfHourStart, SUM(Table2.Euro) AS EURO FROM ( -- 子查询拼接完整时间字符串 SELECT Table1.*, Table1.Day || ' ' || LPAD(Table1.HH, 2, '0') || ':' || LPAD(Table1.MI, 2, '0') || ':' || LPAD(Table1.SS, 2, '0') AS FullTimestamp FROM Table1 ) AS T1 INNER JOIN Table2 ON Table2.NUMOP = T1.NUMOP WHERE T1.DAY = '2024-08-31' GROUP BY T1.DAY, DATEADD( MINUTE, -(EXTRACT(MINUTE FROM CAST(FullTimestamp AS TIMESTAMP)) % 30), CAST(FullTimestamp AS TIMESTAMP) )
说明:
- 子查询中用
LPAD补全时分秒的两位格式,确保拼接出的时间字符串符合Firebird的时间戳识别规范(如2024-08-31 08:15:00) EXTRACT(MINUTE FROM ...) % 30计算当前分钟距离最近半小时起点的偏移量,用DATEADD减去该偏移量实现截断- 最终分组键是精确的半小时起始时间戳,适合需要后续时间运算的场景
内容的提问来源于stack exchange,提问作者Daniele
相关产品推荐
相关产品推荐

