1

それぞれの最新の 4 つの日付を取得したいと考えていましたsymbolidここでコードを次のように調整しました。

set @num := 0, @symbolid := '';
select symbolid, date,
@num := if(@symbolid = symbolid, @num + 1, 1) as row_number,
@symbolid := symbolid as dummy
from projections
group by symbolid, date desc
having row_number < 5

次の結果が得られます。

symbolid                date   row_number   dummy       
1       '2011-09-01 00:00:00'       1       1
1       '2011-08-31 00:00:00'       3       1
1       '2011-08-30 00:00:00'       5       1
2       '2011-09-01 00:00:00'       1       2
2       '2011-08-31 00:00:00'       3       2
2       '2011-08-30 00:00:00'       5       2
3       '2011-09-01 00:00:00'       1       3
3       '2011-08-31 00:00:00'       3       3
3       '2011-08-30 00:00:00'       5       3
4       '2011-09-01 00:00:00'       1       4
...

明らかな疑問は、なぜ ごとに 3 行しか得られないのsymbolidか、そしてなぜ 1、3、5 の番号が付けられているのかということです。いくつかの詳細:

  1. インデックスを強制する場合としない場合の両方を試してみましたが (ここで見られるように)、両方の方法で同じ結果が得られました。
  2. 日付は正しいです。つまり、リストには ごとsymbolidに上位 3 つの日付が正しく表示されますが、row_number の値はずれています
  3. 「having」ステートメントを使用しない場合、行番号は正しいです。つまり、最新の日付は 1、次に新しい日付は 2 などです。

明らかに、row_number計算フィールドは「having」句の影響を受けていますが、修正方法がわかりません。

「having」を「having row_number < 7」(6 は 5 と同じ) に変更できることはわかっていますが、それは非常に見苦しく、「動作」させるにはどうすればよいか知りたいと思います。

4

3 に答える 3

2

なぜこのように動作するのかは 100% わかりませんが (おそらく のSELECT前に論理的に処理されるためですORDER BY)、期待どおりに動作するはずです:

SELECT * 
FROM 
(
    select symbolid, date,
    @num := if(@symbolid = symbolid, @num + 1, 1) as row_number,
    @symbolid := symbolid as dummy
    from projections
    INNER JOIN (SELECT @symbolid:=0)c
    INNER JOIN (SELECT @num:=0)d
    group by symbolid, date desc

) a
WHERE row_number < 5
于 2011-09-02T15:52:09.907 に答える
1

ユーザー定義変数がうまく機能しない (こちらを参照)

原則として、ユーザー変数に値を割り当てたり、同じステートメント内で値を読み取ったりしないでください。期待どおりの結果が得られる可能性がありますが、これは保証されません。ユーザー変数を含む式の評価順序は定義されておらず、特定のステートメント内に含まれる要素に基づいて変わる場合があります。さらに、この順序は、MySQL サーバーのリリース間で同じであるとは限りません。SELECT @a, @a:=@a+1, ... では、MySQL は最初に @a を評価し、次に代入を行うと考えるかもしれません。ただし、ステートメントを変更すると (たとえば、GROUP BY、HAVING、または ORDER BY 句を追加することによって)、MySQL が異なる評価順序で実行計画を選択する可能性があります。

これが私の提案です

select symbolid, 
substring_index(group_concat(date order by date desc), ',', 4) as last_4_dates
from projections
group by symbolid

このアプローチの欠点は、日付がグループ化され、
実際に使用する前に分解する必要があることです。

于 2011-09-02T15:49:40.320 に答える
0

最終的なコード:

set @num := 0, @symbolid := '';
select d.* from
(
select symbolid, date,
  @num := if(@symbolid = symbolid, @num + 1, 1) as row_number,
  @symbolid := symbolid as dummy
from projections
order by symbolid, date desc
 ) d
where d.row_number < 5
于 2011-09-02T16:06:32.407 に答える