Groupwise Max与过滤器优化

时间:2015-10-20 16:39:34

标签: mysql sql groupwise-maximum

我正在尝试在我的groupwise max查询中删除子查询,这会给我带来不必要的using temporary

模式

CREATE TABLE IF NOT EXISTS `rates` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `currency_id` int(11) NOT NULL,
  `rate` double NOT NULL,
  `date` date NOT NULL,
  `date_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `my` (`currency_id`,`date_time`),
  KEY `currency` (`currency_id`),
  KEY `date` (`date`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

问题

我希望date_time的最新the max(date) as date1行和date_time的最新date2 < date1currency_id

简单地说:今天的最新货币汇率以及每种货币前一天的最新汇率。

这是我根据此处描述的技术每个组中的前N个提出的解决方案:http://mysql.rjweb.org/doc.php/groupwise_max#top_n_in_each_group

SELECT
        `id`, `currency_id`, `rate`, `date`, `date_time`, `n`
    FROM
      ( SELECT  @prev := '', @n := 0 ) init
    JOIN
      ( SELECT  @n := if(`currency_id` != @prev, 1, @n + 1) AS n,
                @prev := `currency_id`,
                `id`, `currency_id`, `rate`, `date`, `date_time`
            FROM
            ( SELECT *
              FROM
                ( SELECT *
                   FROM
                     `rates`
                   ORDER BY
                     `date_time` DESC ) v
              GROUP BY
                `currency_id`, `date` ) v
            ORDER BY
                `currency_id`   ASC,
                `date_time` DESC
      ) x
    WHERE  n <= 2;

摆弄测试数据:http://sqlfiddle.com/#!9/54229/8

唉,FROM州的子查询生成临时表...我想知道,甚至可以避免临时表上出现高级分组最大问题吗?

修改

好的,我想我在这里得到了一些东西:http://sqlfiddle.com/#!9/54229/55

SELECT
        `id`, `currency_id`, `rate`, `date`, `date_time`
    FROM
      ( SELECT  @prev := '', @prev_date := '', @n := 0, @m := 0 ) init
    JOIN
      ( SELECT  @n := if(`prev` != @prev, 1, @n + if(`date` = @prev_date, 0, 1)) AS n,
                @m := if(`date` != @prev_date, 1, @m + 1) AS m,
                @prev := `prev`,
                @prev_date := `date`,
                `id`, `currency_id`, `rate`, `date`, `date_time`, `prev`
            FROM  (SELECT *, `currency_id` as `prev` FROM `rates`) v
            ORDER BY
                `prev`   ASC,
                `date_time` DESC
      ) x
    WHERE  n <= 2 AND m = 1;

编辑2

最后,我的解决方案:http://sqlfiddle.com/#!9/54229/59

SELECT
        v.`id`, v.`currency_id`, v.`rate`, v2.`rate` as `rate_prev`, v.`rate` - v2.`rate` as `change`, v.`date`, v2.`date` as `date_prev`, v.`date_time`, v2.`date_time` as `date_time_prev`
    FROM
      ( SELECT  @group_by := '', @group_by_date := '', @n := 0, @m := 0 ) init
    JOIN
      ( SELECT  *, 
                @m := if(`date` != @group_by_date, 1, 0) AS `m`,
                @n := if(`group_by` != @group_by, 1, @n + @m) AS `n`,
                @group_by := `group_by`,
                @group_by_date := `date`
            FROM  (SELECT *, `currency_id` as `group_by` FROM `rates` ORDER BY `currency_id`, `date` DESC, `date_time` DESC) v
      ) v ON v.n = 1 AND v.m = 1
    LEFT JOIN
      ( SELECT  *, 
                @m := if(`date` != @group_by_date, 1, 0) AS `m`,
                @n := if(`group_by` != @group_by, 1, @n + @m) AS `n`,
                @group_by := `group_by`,
                @group_by_date := `date`
            FROM  (SELECT *, `currency_id` as `group_by` FROM `rates` ORDER BY `currency_id`, `date` DESC, `date_time` DESC) v
      ) v2 ON v.currency_id = v2.currency_id AND v2.n = 2 AND v2.m = 1

O(n)表现,没有临时表。我还加入了结果,以便在单行中获得费率变化。

0 个答案:

没有答案