【问题标题】:Obtain the last [n,n+t] days per group获取每组的最后 [n,n+t] 天
【发布时间】:2015-09-06 19:15:08
【问题描述】:

首先,请原谅语言,我一直无法将我的问题解析为实际的英语,所以如果有人可以编辑以使其更清晰,那将有所帮助。

我已经为此苦苦挣扎了一段时间。我需要一个查询,对于每个组,从过去 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 */

【问题讨论】:

  • 我在我的 groupwise max 博客中讨论了一个解决方案:(mysql.rjweb.org/doc.php/groupwise_max)。

标签: mysql sql mariadb heidisql


【解决方案1】:

一种可行的方法是使用用户变量对每个组中的行进行编号,然后将结果限制为具有所需间隔的行号的行:

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 |

【讨论】:

    【解决方案2】:
    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-22
      • 1970-01-01
      • 2016-11-26
      • 1970-01-01
      • 2022-12-07
      • 2019-02-07
      相关资源
      最近更新 更多