MySQL:选择每个月的最后一组记录

时间:2015-06-22 17:34:09

标签: mysql

每月几次,新的一组记录被添加到表certificant_region_stats中,并具有相同的时间戳certificants_modified。我正试图从每月的最后一次抽射中选择所有记录。

我的尝试崩溃了我的控制台:

SELECT * 
FROM certificant_region_stats 
WHERE certificants_modified
    IN (
        SELECT   MAX(certificants_modified)
        FROM     certificant_region_stats
        GROUP BY YEAR(certificants_modified), MONTH(certificants_modified)
    ) 
ORDER BY certificants_modified DESC;

子查询可以自行运行,所以我猜我使用的是错误的吗?

编辑:样本数据

| id | country | certificants_number | certificants_modified | 
==============================================================
| 1  | USA     | 2                   | 2015-06-22 10:24:55   |
| 2  | Canada  | 4                   | 2015-06-22 10:24:55   |
| 3  | USA     | 5                   | 2015-06-09 09:18:24   |
| 4  | Canada  | 6                   | 2015-06-09 09:18:24   |
| 5  | USA     | 8                   | 2015-05-15 11:30:00   |
| 6  | Canada  | 8                   | 2015-05-15 11:30:00   |
| 7  | USA     | 3                   | 2015-05-02 08:45:01   |
| 8  | Canada  | 7                   | 2015-05-02 08:45:01   |

我希望它能从第1,2,5和6行返回*。

2 个答案:

答案 0 :(得分:0)

SELECT组中最佳行的一个好策略是LEFT JOIN一个表自身,所有组列相等,然后找到没有更好行的行。它可能看起来像这样:

SELECT crs.*
FROM certificant_region_stats AS crs
LEFT JOIN certificant_region_stats AS better
ON YEAR(crs.certificants_modified) = YEAR(better.certificants_modified)
   AND MONTH(crs.certificants_modified) = MONTH(better.certificants_modified)
   AND crs.country = better.country
   AND crs.certificants_modified < better.certificants_modified
WHERE better.id IS NULL

或者你可以使用LAST_DAY function来保存年份和月份并丢弃日期和时间,如下所示:

SELECT crs.*
FROM certificant_region_stats AS crs
LEFT JOIN certificant_region_stats AS better
ON LAST_DAY(crs.certificants_modified) = LAST_DAY(better.certificants_modified)
   AND crs.country = better.country
   AND crs.certificants_modified < better.certificants_modified
WHERE better.id IS NULL

此答案中的代码为双重许可:CC BY-SA 3.0MIT License as published by OSI

答案 1 :(得分:0)

这是一个解决方案。它使用表达式来抓取每个月的第一天,然后提取该月的最后一批数据。

SELECT DATE(DATE_FORMAT(crs.certificants_modified, '%Y-%m-01')) month_begin,
       crs.id, crs.country, crs.certificants_modified
  FROM certificant_region_stats crs
  JOIN (
       SELECT MAX(certificants_modified) lastmod,
              DATE(DATE_FORMAT(certificants_modified, '%Y-%m-01')) month_begin
         FROM certificant_region_stats
        GROUP BY DATE(DATE_FORMAT(certificants_modified, '%Y-%m-01'))
        ) last ON crs.certificants_modified = last.lastmod
 ORDER BY month_begin, crs.id

看到这个。 http://sqlfiddle.com/#!9/3b386/3/0