0

我试图在这里摆脱我的分组最大查询中的子查询,这给了我不想要的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_timethe max(date) as date1行和每个最新date_time的行。date2 < date1currency_id

简单来说:每种货币的今天最新汇率和前一天最新汇率。


这是我根据此处描述的每个组中的 Top-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)性能和没有临时表。我还将结果加入到自身中以获取单行中的速率变化。

4

0 回答 0