4

価格情報を保持するテーブルがあります。3 行ごとに最大値を選択する必要があります。例:

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 を比較したら、テーブルに含まれるすべての値 (現在約 400,000 の値) に対してこれを行うまで、4 から 6、7 から 9 などに移動します。を使用するコードを書きました。

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

これは機能しますが、非常に遅いです。クエリの SELECT 部分と FROM 部分の間を意味する、表示用にプルする列の値を識別する SELECT ステートメントを使用してみました。

比較のために JOIN を使用して 3 つの行すべてを同じテーブルに結合しようとしましたが、これも非常に遅いです。遅いとは、20 行の情報を収集するのに 10 秒弱かかることを意味します。これは、クエリが 9.65879893303 秒で 60 行 (3 つのグループが 20 行) を分析したことを意味します (私はこれを作成しませんでした。計算には 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

例を挙げてより完全な答え。次のコードは、私があなたが望むと思うことを行います。

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

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

以下のクエリは、テストテーブルで機能しました。おそらく最善ではありませんが、他のソリューションは私のテストテーブルで失敗しました.

これには、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
于 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 に答える