mysql查询速度 - 选择每3行的最大值

时间:2012-11-28 09:19:37

标签: php mysql performance

我有一张包含价格信息的表格。我需要选择每三行的最大值。实施例:

Table `daily_high`
 ____ _______
| ID | HIGH  |
| 1  | 24.65 |
| 2  | 24.93 |
| 3  | 26.02 |
| 4  | 25.33 |
| 5  | 25.16 |
| 6  | 25.91 |
| 7  | 26.05 |
| 8  | 28.13 |
| 9  | 27.07 |
|____|_______|


Desired output to new table (ID will be auto-increment so don't assume an association exists between this ID 1 and the daily_high ID 1:
 ____ ___________
| ID | 3MaxHIGH  |
|____|___________|
| 1  | 26.02     |
| 2  | 25.91     |
| 3  | 28.13     |
|____|___________|

我想比较ID 1,2和3以确定它们之间的高值。然后,一旦我比较了1-3,我想继续进行4到6,然后是7到9等,直到我为表中包含的所有值(目前大约400,000个值)完成此操作。我编写了使用

的代码

SELECT max(HIGH) FROM daily_high as dh1 JOIN (SELECT max(HIGH) FROM daily_high WHERE id >= dh1 AND id < (dh1.id + 3))

这可行,但速度非常慢。我已经尝试使用SELECT语句来识别要显示的列值,这意味着在查询的SELECT和FROM部分之间。

我尝试使用JOIN将所有3行连接到同一个表上进行比较,但它也非常慢。慢了我的意思是在不到10秒的时间内收集20行的信息。这意味着查询已经在9.65879893303秒内分析了60行(20组3个)(我没有这样做,我使用microtime()来计算它。

对于比我更快的代码,任何人都有任何建议吗?

请记住,我的实际表格与上面发布的表格不同,但概念是相同的。

感谢您的帮助。

5 个答案:

答案 0 :(得分:1)

如果您持续识别,则可以进行此操作

SELECT floor(id/3) as range, max(HIGH) FROM daily_high GROUP BY range;

答案 1 :(得分:0)

为什么不使用DIV运算符对聚合进行分组:

SELECT (id-1) DIV 3 + 1 AS ID, MAX(high) AS 3MaxHIGH 
FROM daily_high 
GROUP BY (id-1) DIV 3

此查询提供相同的结果。

ID  3MaxHIGH
1   26.02
2   25.91
3   28.13

我无法运行您的查询,我相信这个更快。

UPD :为确保您拥有有效范围的群组,请使用此查询:

select id, high, (id-1) div 3 + 1 from daily_high

结果:

id  high    (id-1) div 3 + 1
1   24.65   1
2   24.93   1
3   26.02   1
4   25.33   2
5   25.16   2
6   25.91   2
7   26.05   3
8   28.13   3
9   27.07   3

答案 2 :(得分:0)

富勒以一个例子回答。以下代码将执行我认为您想要的操作。

SELECT FLOOR((row - 1) / 3), MAX(Sub1.high)
FROM (SELECT @row := @row + 1 as row, daily_high.*
FROM daily_high, (SELECT @row := 0) r) Sub1
GROUP BY FLOOR((row - 1) / 3) 
ORDER BY Sub1.ID

答案 3 :(得分:0)

以下查询在测试表上为我工作。也许不是最好的,但其他解决方案在我的测试台上失败了。

这确实要求ID是顺序的。另外一定要把一个索引放在High以及速度上。

SELECT FLOOR(T1.Id/3)+1 AS Id, ROUND(GREATEST(T1.High, T2.High, T3.High),2) AS High FROM `daily_high` T1, `daily_high` T2, `daily_high` T3
WHERE T2.Id=T1.Id+1 
AND T3.Id=T2.Id+1
AND MOD(T1.Id, 3)=1

答案 4 :(得分:0)

logic: if(id is divisible by 3, id/3-1, id/3)

select if(mod(id,3) = 0,floor(id/3)-1,floor(id/3)) as group_by_col , max(HIGH)
FROM daily_high GROUP BY group_by_col;