【发布时间】:2011-03-26 11:51:32
【问题描述】:
抱歉,问题的标题有点模糊,所以这是一个工作示例。
我有一个表,每个用户(用户 ID)每隔几天就会在其中获取一个值。我想为每个用户找到这些值中的最后一个,按月细分,并将它们的数量计算到一个范围内。
这是一个示例表和代表性数据:
CREATE TABLE `datasource` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`userId` INT UNSIGNED NOT NULL ,
`unixts` INT UNSIGNED NOT NULL ,
`value` INT UNSIGNED NOT NULL ,
INDEX ( `userId` )
);
INSERT INTO `datasource`
(`userId`, `unixts`, `value`)
VALUES
(1, UNIX_TIMESTAMP('2010-07-01'), 500),
(1, UNIX_TIMESTAMP('2010-07-15'), 610),
(1, UNIX_TIMESTAMP('2010-08-02'), 740),
(2, UNIX_TIMESTAMP('2010-07-03'), 506),
(2, UNIX_TIMESTAMP('2010-07-18'), 640),
(2, UNIX_TIMESTAMP('2010-08-09'), 340),
(3, UNIX_TIMESTAMP('2010-07-03'), 506),
(3, UNIX_TIMESTAMP('2010-08-18'), 640)
;
现在,这里有一个查询来获取我想要的内容:
select
month(FROM_UNIXTIME(unixts)) as month,
sum( if( value >= 700, 1, 0) ) as '700 and up',
sum( if( value BETWEEN 600 AND 699, 1, 0) ) as '600-699',
sum( if( value BETWEEN 500 AND 599, 1, 0) ) as '500-599',
sum( if( value <= 499, 1, 0) ) as '499 and below',
count(*) as total
from
datasource
where
id in (
select
max(id)
from
datasource
where
unixts between UNIX_TIMESTAMP('2010-07-01') and UNIX_TIMESTAMP('2010-09-01')
group by
userId, month(from_unixtime(unixts))
)
group by
month(FROM_UNIXTIME(unixts));
+-------+------------+---------+---------+---------------+-------+
| month | 700 and up | 600-699 | 500-599 | 499 and below | total |
+-------+------------+---------+---------+---------------+-------+
| 7 | 0 | 2 | 1 | 0 | 3 |
| 8 | 1 | 1 | 0 | 1 | 3 |
+-------+------------+---------+---------+---------------+-------+
此查询非常适合我们的小型结果集。但是,如果您将 4400 万行放入数据源表中,它就会停止运行。
有没有一种优化的方法来编写这个查询,可以实现我想要的,而不用把 mysql 挂上几天?
【问题讨论】: