获取每个组的最后 [n,n+t] 天
Obtain the last [n,n+t] days per group
首先,请原谅我的语言,我一直无法将我的问题解析为实际的英语,所以如果有人可以编辑以使其更清楚,那将会有所帮助。
我为此苦苦挣扎了一段时间。我需要一个查询,对于每个组,从过去 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');
在tabletrying
中有三个types1
'types':'one'、'two'和'three',还有每组 5 个观察值。请注意,各组之间的日期不相似,它们之间甚至可能存在差距 (so no dates BETWEEN, like in this question)。
在这个例子中,我想得到一个 table 每组三个中间值。所以跳过第一个和最后一个值,预期的输出将如下所示:
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 */
一种可行的方法是使用用户变量对每组中的行进行编号,然后将结果限制为行号在所需间隔内的行:
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
或者,如果您总是想删除每个组中的第一行和最后一行,那么您可以对派生的 table 使用左联接,其中 return 是每个组的最大和最小日期群组:
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
使用您的示例数据,两个查询 return 相同的结果:
| 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 |
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
首先,请原谅我的语言,我一直无法将我的问题解析为实际的英语,所以如果有人可以编辑以使其更清楚,那将会有所帮助。
我为此苦苦挣扎了一段时间。我需要一个查询,对于每个组,从过去 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');
在tabletrying
中有三个types1
'types':'one'、'two'和'three',还有每组 5 个观察值。请注意,各组之间的日期不相似,它们之间甚至可能存在差距 (so no dates BETWEEN, like in this question)。
在这个例子中,我想得到一个 table 每组三个中间值。所以跳过第一个和最后一个值,预期的输出将如下所示:
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 */
一种可行的方法是使用用户变量对每组中的行进行编号,然后将结果限制为行号在所需间隔内的行:
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
或者,如果您总是想删除每个组中的第一行和最后一行,那么您可以对派生的 table 使用左联接,其中 return 是每个组的最大和最小日期群组:
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
使用您的示例数据,两个查询 return 相同的结果:
| 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 |
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