我正在尝试在我的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 < date1
行currency_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;
最后,我的解决方案: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)
表现,没有临时表。我还加入了结果,以便在单行中获得费率变化。