4

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

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() 来计算它。

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

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

谢谢你的帮助。

4

5 回答 5

1

如果你连续识别它,你可以做到这一点

SELECT floor(id/3) as range, max(HIGH) FROM daily_high GROUP BY range;
于 2012-11-28T09:37:08.010 回答
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
于 2012-11-28T09:37:12.823 回答
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
于 2012-11-28T09:43:09.117 回答
0

下面的查询在测试表上对我有用。也许不是最好的,但其他解决方案在我的测试表上失败了。

这确实要求 ID 是连续的。还要确保将索引设置为“高”以提高速度。

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
于 2012-11-28T09:45:47.070 回答
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;
于 2012-11-28T09:49:17.640 回答