2015-09-06 3 views
0

Прежде всего, пожалуйста, извините за язык, у меня возникли проблемы с разбором моей проблемы на английском, поэтому, если кто-нибудь может отредактировать, чтобы сделать ее более ясной, что поможет.Получить последние [n, n + t] дней за группу

Я некоторое время боролся с этим. Мне нужен запрос, который по каждой группе из последних N дней пропускает самую последнюю и получает следующие T дней. Это версия классической проблемы «LIMIT with GROUP», и на самом деле один из запросов, которые я пробовал, который не работал, использовал эту форму.

MRE следующим образом:

CREATE TABLE `trying` (id INTEGER PRIMARY KEY AUTO_INCREMENT, types1 TEXT, stuffs INTEGER, dates DATE); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("one",123,'2015-09-06'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("one",67,'2015-09-05'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("one",45,'2015-09-04'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("one",98,'2015-09-03'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("one",89,'2015-09-02'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("two",56,'2015-09-02'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("two",34,'2015-09-01'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("two",98,'2015-08-31'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("two",34,'2015-08-30'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("two",12,'2015-08-29'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("three",3,'2015-09-06'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("three",8,'2015-09-04'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("three",80,'2015-09-02'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("three",9,'2015-09-01'); 
INSERT INTO `trying`(types1, stuffs, dates) VALUES("three",6,'2015-08-31'); 

В таблице trying есть три types1 'типа': 'один', 'два' и 'три', и есть 5 наблюдений в каждой группе. Обратите внимание, что даты не совпадают между группами, и между ними могут быть пробелы (so no dates BETWEEN, like in this question).

В этом примере я хотел бы получить таблицу с тремя средними значениями для каждой группы. Так пропустить первое и последнее значение, ожидаемый результат будет выглядеть следующим образом:

types1 stuffs dates 
one  67  2015-09-05 
one  45  2015-09-04 
one  98  2015-09-03 
two  34  2015-09-01 
two  98  2015-08-31 
two  34  2015-08-30 
three 8  2015-09-04 
three 80  2015-09-02 
three 9  2015-09-01 

Несколько запросов, которые не работают:

SELECT types1, stuffs, dates FROM trying GROUP BY types1 LIMIT 2,4; 
/*this returned the following */ 
types1 stuffs dates 
two  56  2015-09-02 


SELECT trying.* FROM (SELECT types1, stuffs, dates FROM trying) GROUP BY trying.types1 OFFSET 2,4; 
/*threw out an error: Every derived table must have its own alias */ 
+0

Я обсудить решение в м y groupwise max blog: (mysql.rjweb.org/doc.php/groupwise_max). –

ответ

1
select types1,stuffs,dates from (
select @rank:=if(@prev_cat=types1,@rank+1,1) as rank, 
    types1,stuffs,dates,@prev_cat:=types1 

from trying,(select @rank:=0, @prev_cat:="")t 
order by types1, dates desc 
) temp 

    where rank between 2 and 4 
2

Один из способов, которые могли бы работать, чтобы использовать пользовательские переменные для номер строки в каждой группе, а затем ограничить результат к строкам с номером строки в требуемом интервале:

SELECT id, types1, stuffs, dates 
FROM (
    SELECT 
    id, types1, stuffs, dates, 
    (
     CASE types1 
     WHEN @type 
     THEN @row := @row + 1 
     ELSE @row := 1 AND @type := types1 END 
    ) + 1 AS row 
    FROM trying p, 
    (SELECT @row := 0, @type := '') r 
    ORDER BY types1, dates asc 
) src 
WHERE row BETWEEN 2 AND 4 
ORDER BY id; 

Sample SQL Fiddle для запроса 1

Или, если вы всегда хотите удалить первые и последние строки в каждой группе, то вы можете использовать левое соединение к производной таблице, которая возвращает максимальную и мин даты для каждой группы:

select t.* from trying t 
left join (
    select types1, min(dates) min_dates, max(dates) max_dates 
    from trying group by types1 
    ) minmax 
    on t.types1 = minmax.types1 
    and t.dates in (minmax.max_dates, minmax.min_dates) 
where minmax.types1 is null; 

Sample SQL Fiddle для запрос 2

с вашими данными выборки оба запроса возвращают один и тот же результат:

| id | types1 | stuffs |      dates | 
|----|--------|--------|-----------------------------| 
| 2 | one |  67 | September, 05 2015 00:00:00 | 
| 3 | one |  45 | September, 04 2015 00:00:00 | 
| 4 | one |  98 | September, 03 2015 00:00:00 | 
| 7 | two |  34 | September, 01 2015 00:00:00 | 
| 8 | two |  98 | August, 31 2015 00:00:00 | 
| 9 | two |  34 | August, 30 2015 00:00:00 | 
| 12 | three |  8 | September, 04 2015 00:00:00 | 
| 13 | three |  80 | September, 02 2015 00:00:00 | 
| 14 | three |  9 | September, 01 2015 00:00:00 | 
Смежные вопросы