基于FP_BASIC_BD表按周计算高低价均值的SQL查询需求
Oracle 按周计算指定指标的SQL实现
首先先明确你的表结构,我把它整理成标准的SQL建表语句方便参考:
CREATE TABLE FP_BASIC_BD ( FS_ID VARCHAR2(20) NOT NULL, TRADE_DATE DATE NOT NULL, -- 注:原字段名`DATE`是Oracle关键字,建议改成非关键字名称,下面SQL用`TRADE_DATE`演示 CURRENCY CHAR(3), PRICE FLOAT(126), PRICE_OPEN FLOAT(126), PRICE_HIGH FLOAT(126), PRICE_LOW FLOAT(126), VOLUME FLOAT(126) );
接下来是满足你需求的单条SQL查询,我把日期逻辑完全整合到了查询里,不需要额外分步处理:
WITH weekly_base AS ( SELECT FS_ID, -- 计算本周的基准周一(不管当天有没有数据) TRUNC(TRADE_DATE, 'IW') AS base_week_monday, -- 计算本周的基准周五(不管当天有没有数据) TRUNC(TRADE_DATE, 'IW') + 4 AS base_week_friday, TRADE_DATE, PRICE_HIGH, PRICE_LOW FROM FP_BASIC_BD -- 可选:指定特定FS_ID,比如 WHERE FS_ID = 'XYZ123',去掉则查询所有FS_ID ), weekly_agg AS ( SELECT FS_ID, base_week_monday, base_week_friday, -- 获取周末日期:优先周五,无数据则取本周一到周五间最近的可用日期 COALESCE( MAX(CASE WHEN TRADE_DATE = base_week_friday THEN TRADE_DATE END), MAX(TRADE_DATE) FILTER (WHERE TRADE_DATE BETWEEN base_week_monday AND base_week_friday) ) AS weekend_date, -- 获取周起始日期:优先周一,无数据则取本周一到周末日期间最近的可用日期 COALESCE( MIN(CASE WHEN TRADE_DATE = base_week_monday THEN TRADE_DATE END), MIN(TRADE_DATE) FILTER (WHERE TRADE_DATE BETWEEN base_week_monday AND base_week_friday) ) AS week_start_date, -- 计算本周(PRICE_HIGH+PRICE_LOW)的平均值 AVG(PRICE_HIGH + PRICE_LOW) AS avg_high_low_sum FROM weekly_base GROUP BY FS_ID, base_week_monday, base_week_friday ) SELECT FS_ID, weekend_date, week_start_date, ROUND(avg_high_low_sum, 2) AS avg_high_low_sum -- 可选:给平均值保留两位小数 FROM weekly_agg ORDER BY FS_ID, weekend_date DESC;
逻辑说明:
weekly_baseCTE:给每条交易数据标记它所在周的基准周一和周五(用TRUNC(TRADE_DATE, 'IW')获取ISO周的周一,加4天得到周五),明确每周的时间范围。weekly_aggCTE:按FS_ID和周基准分组完成核心操作:- 用
COALESCE优先取周五日期,若无则取本周一到周五间最晚的可用日期作为周末日期; - 同样用
COALESCE优先取周一日期,若无则取本周一到周末日期间最早的可用日期作为周起始日期; - 直接计算本周所有数据的
PRICE_HIGH+PRICE_LOW平均值。
- 用
- 最后主查询整理输出结果,可按需用
ROUND调整平均值格式。
注意事项:
- 如果你的表字段名确实是
DATE,记得把SQL里的TRADE_DATE全部替换回去,不过强烈建议修改字段名避免关键字冲突; - 要查询特定FS_ID的话,在
weekly_base的FROM后添加WHERE FS_ID = '你的目标FS_ID'即可。
内容的提问来源于stack exchange,提问作者Shekhar Nalawade
相关产品推荐
相关产品推荐

