简体   繁体   English

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

[英]mysql speed of query - selecting max value of every 3 rows

I have a table that holds price information. 我有一张包含价格信息的表格。 I need to select the max value of every three rows. 我需要选择每三行的最大值。 EXAMPLE: 例:

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     |
|____|___________|

I want to compare IDs 1,2, and 3 to determine the high value among them. 我想比较ID 1,2和3来确定它们之间的高值。 Then once I have compared 1-3, I want to move on to 4 through 6, then 7 through 9, etc until I've done this for all values contained in the table (currently about 400,000 values). 然后,一旦我比较了1-3,我想继续进行4到6,然后是7到9等,直到我为表中包含的所有值(目前大约400,000个值)完成此操作。 I have written code that uses 我编写了使用的代码

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

This works but is horribly slow. 这有效,但速度非常慢。 I've tried using the SELECT statement where I identify the column values to be pull for display, meaning between the SELECT and FROM parts of the query. 我已经尝试使用SELECT语句,我在其中标识要显示的列值,这意味着在查询的SELECT和FROM部分之间。

I've tried to use JOIN to join all 3 rows onto the same table for comparison but it too is horribly slow. 我试图使用JOIN将所有3行连接到同一个表上进行比较,但它也非常慢。 By slow I mean just under 10 seconds to gather information for 20 rows. 慢了我的意思是在不到10秒的时间内收集20行的信息。 This means that the query has analyzed 60 rows (20 groups of 3) in 9.65879893303 seconds (I didn't make this up, I used microtime() to calculate it. 这意味着查询在9.65879893303秒内分析了60行(20组3个)(我没有这样做,我用microtime()来计算它。

Anyone have any suggestions for faster code than what I've got? 任何人都有任何建议比我更快的代码?

Keep in mind that my actual table is not the same as what I've posted above, but it the concept is the same. 请记住,我的实际表格与我上面发布的表格不同,但概念是相同的。

Thanks for any help. 谢谢你的帮助。

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

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

Why not to use DIV operator for grouping your aggregation: 为什么不使用DIV运算符对聚合进行分组:

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

This query gives the same result. 此查询给出相同的结果。

ID  3MaxHIGH
1   26.02
2   25.91
3   28.13

I was unable to run your query, and I believe that this one is faster. 我无法运行您的查询,我相信这个更快。

UPD : To ensure that you have valid groups for your ranges, use this query: UPD :要确保您拥有范围的有效组,请使用以下查询:

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

result: 结果:

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

Fuller answer with an example. 富勒以一个例子回答。 The following code will do what I think you want. 以下代码将执行我认为您想要的操作。

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

The below query worked for me on a test table. 以下查询在测试表上为我工作。 perhaps not the best, but the other solutions failed on my test table. 也许不是最好的,但其他解决方案在我的测试表上失败了。

This does require the ID's to be sequential. 这确实要求ID是顺序的。 Also be sure to put an index on High aswell for speed. 另外一定要把一个索引放在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
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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM