2015-06-22 4 views
0

Несколько раз в месяц к таблице certant_region_stats добавляется новый залп записей с идентичной меткой времени, certants_modified. Я пытаюсь выбрать все записи из последнего залпа в месяц.MySQL: выберите последний набор записей за каждый месяц

Мои попытки разбить мою консоль:

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; 

подзапрос прекрасно работает сам по себе, так что я предполагаю, что я использую в неправильном?

EDIT: выборочные данные

| 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.

+0

Пожалуйста, разместите небольшой образец строк из таблицы 'certant_region_stats' вместе с тем, что вы ожидаете от вывода запроса. Неясно, уникально ли значение 'certants_modified', или комбинация этого значения вместе с датами делает его уникальным. –

+0

@MichaelBerkowski, см. Мое редактирование – GreenTaq

+0

Что означает «сбой моей консоли»? Как я вижу, ваш запрос идеально подходит для этой задачи. Кстати, индекс на certants_modified должен оказаться полезным. –

ответ

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.0 или MIT License as published by OSI.

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

Смежные вопросы