SQL技术问询:获取首尾行及月度金属价格统计异常问题
解决方案
嘿,我来帮你搞定这两个技术问题:
一、获取数据集的首行与末行
获取首行和末行的思路很直接,不同数据库语法略有差异,但核心逻辑一致:
- 首行:按你需要的排序字段升序排列后取第一条。比如MySQL里可以这么写:
要是用SQL Server,把SELECT * FROM your_table ORDER BY sort_column LIMIT 1;LIMIT 1换成TOP 1就行。 - 末行:把排序方向改成降序,再取第一条:
如果想一次性拿到首行和末行,用SELECT * FROM your_table ORDER BY sort_column DESC LIMIT 1;UNION ALL把两个结果合并:
注意:如果排序字段有重复值,最好再加个辅助排序字段(比如主键),确保拿到的是你真正想要的首/末行。(SELECT * FROM your_table ORDER BY sort_column LIMIT 1) UNION ALL (SELECT * FROM your_table ORDER BY sort_column DESC LIMIT 1);
二、修改查询为整月统计&解决metal_id=2无数据问题
先分析下你的问题:原查询按日统计,现在要改成整月的整体min、max、起始/结束价格,同时metal_id=2切换后没数据。我给你整理两种可行的写法:
方法1:用窗口函数实现(简洁高效)
窗口函数可以直接帮我们拿到整月的起始和结束价格,同时计算min和max:
SELECT DISTINCT metal_id, MIN(price) OVER (PARTITION BY metal_id) AS monthly_min_price, MAX(price) OVER (PARTITION BY metal_id) AS monthly_max_price, FIRST_VALUE(price) OVER (PARTITION BY metal_id ORDER BY created_at) AS monthly_start_price, LAST_VALUE(price) OVER (PARTITION BY metal_id ORDER BY created_at ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS monthly_end_price FROM your_table WHERE created_at BETWEEN '2023-01-01' AND '2023-01-31'; -- 替换成你要的月份
如果你只需要最后2个价格(也就是起始和结束价格),删掉min和max的字段就行。
方法2:用子查询关联(兼容性更强)
要是你的数据库不支持窗口函数,可以用子查询来获取每个metal_id当月的最早和最晚价格:
SELECT t.metal_id, MIN(t.price) AS monthly_min_price, MAX(t.price) AS monthly_max_price, start_price.price AS monthly_start_price, end_price.price AS monthly_end_price FROM your_table t LEFT JOIN ( SELECT metal_id, price FROM your_table WHERE created_at = (SELECT MIN(created_at) FROM your_table WHERE metal_id = t.metal_id AND created_at BETWEEN '2023-01-01' AND '2023-01-31') ) start_price ON t.metal_id = start_price.metal_id LEFT JOIN ( SELECT metal_id, price FROM your_table WHERE created_at = (SELECT MAX(created_at) FROM your_table WHERE metal_id = t.metal_id AND created_at BETWEEN '2023-01-01' AND '2023-01-31') ) end_price ON t.metal_id = end_price.metal_id WHERE t.created_at BETWEEN '2023-01-01' AND '2023-01-31' GROUP BY t.metal_id, start_price.price, end_price.price;
关于metal_id=2无数据的问题
先排查两个点:
- 确认
metal_id=2在你指定的月份里有没有数据,直接跑SELECT * FROM your_table WHERE metal_id=2 AND created_at BETWEEN '指定月份的起止日期';看看结果。 - 如果有数据但原查询没返回,大概率是原按日分组的逻辑导致(比如某一天没数据,但整月有),换成上面的整月分组写法后应该就能正常返回了。
内容的提问来源于stack exchange,提问作者Dean Chambers
相关产品推荐
相关产品推荐

