如何按月分组取首条记录?SQL查询需求及实现问询
问题分析与解答
原始需求与示例数据
我有如下DataFrame数据:
| Date | Name | NumberID |
|---|---|---|
| 05-JAN-2022 | Test | 1 |
| 07-JAN-2022 | Test | 1 |
| 09-FEB-2022 | Test | 1 |
| 10-FEB-2022 | Test | 1 |
| 11-FEB-2022 | Test | 1 |
| 12-MAR-2022 | Test | 1 |
| 02-MAR-2022 | Test | 1 |
需要返回每个月份下对应Name和NumberID组合的最早日期,结果如下:
| Date | Name | NumberID |
|---|---|---|
| 05-JAN-2022 | Test | 1 |
| 09-FEB-2022 | Test | 1 |
| 02-MAR-2022 | Test | 1 |
注意:不能直接指定日期列表筛选,因为日期数量庞大且未知。
更复杂的示例数据(同一月份存在不同Name):
| Date | Name | NumberID |
|---|---|---|
| 05-JAN-2022 | Test | 1 |
| 07-JAN-2022 | Test | 1 |
| 09-FEB-2022 | Test | 1 |
| 10-FEB-2022 | Test | 1 |
| 11-FEB-2022 | Test1 | 1 |
| 12-MAR-2022 | Test | 1 |
| 02-MAR-2022 | Test | 1 |
期望输出(同一月份不同Name各自取最早日期):
| Date | Name | NumberID |
|---|---|---|
| 05-JAN-2022 | Test | 1 |
| 09-FEB-2022 | Test | 1 |
| 11-FEB-2022 | Test1 | 1 |
| 02-MAR-2022 | Test | 1 |
你的SQL语句存在的问题
你编写的SQL无法满足需求,问题如下:
SELECT tc.TITLETest, MIN(tc.DATETest) AS YOURDATE, tc.CRSTest FROM Table tc WHERE tc.TC= 1 GROUP BY EXTRACT(MONTH FROM YOURDATE),tc.TITLETest,tc.CRSTest ORDER BY YOURDATE
- 语法错误:
GROUP BY子句中使用了YOURDATE别名,但别名是在SELECT阶段生成的,多数SQL数据库(如MySQL、PostgreSQL)不允许在分组阶段直接引用,会导致执行报错。 - 逻辑漏洞:
- 未考虑年份分组,若存在跨年份的同月份数据,会被错误合并;
- 假设
TITLETest对应Name、CRSTest对应NumberID,当前分组逻辑未明确区分同一月份下的不同Name组合,无法匹配复杂示例的需求。
正确的SQL写法
假设表名为your_table,字段对应关系为Date→DATETest、Name→TITLETest、NumberID→CRSTest,正确语句如下:
SELECT tc.TITLETest AS Name, MIN(tc.DATETest) AS Date, tc.CRSTest AS NumberID FROM your_table tc WHERE tc.TC = 1 GROUP BY EXTRACT(YEAR FROM tc.DATETest), EXTRACT(MONTH FROM tc.DATETest), tc.TITLETest, tc.CRSTest ORDER BY Date;
逻辑说明:
- 按
年份+月份+Name+NumberID分组,确保不同年份、不同名称的同月份数据不会被合并; - 对每个分组取最小日期,完全匹配两个示例的期望输出;
- 分组时使用原始字段而非别名,避免语法错误。
内容的提问来源于stack exchange,提问作者TourEiffel
相关产品推荐
相关产品推荐

