これが質問1の解決策です。これは、全表スキャンと依存サブクエリが多数あるため、はるかに高速に実行されます。ここでは、せいぜい1つのテーブルスキャンしかありません(データの大きさやメモリの量によっては、一時テーブルもあります)。ここであなたの質問に簡単に合わせることができると思います。質問2(私は実際には読んでいません)もおそらく答えられます。where date_column = whatever
を追加するだけで簡単にできるからです。
select * from (
select
t.*,
if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,
@prev_sn := SerialNumber,
@prev_toner := Remain_Toner_Black
from
Table1 t
, (select @prev_toner:=0, @prev_sn:=SerialNumber from Table1 order by SerialNumber limit 1) var_init
order by SerialNumber, id
) sq
where select_it = 1
- sqlfiddle でライブで動作することを確認してください
編集:
説明:
この行で
, (select @prev_toner:=0, @prev_sn:=SerialNumber from Table1 order by SerialNumber
変数@prev_toner
を初期化するだけです および@prev_sn
急いで。これは、クエリにこの行がまったく含まれていないのと同じですが、クエリの前に書き込みます
SET @prev_toner = 0;
SET @prev_sn = (select serialnumber from your_table order by serialnumber limit 1);
SELECT ...
では、なぜ@prev_snに値を割り当てるクエリを実行するのでしょうか。また、シリアル番号で並べ替えるのはなぜですか。による順序は非常に重要です。による順序がないと、行が返される保証された順序はありません。また、変数を使用して前の行の値にアクセスするため、同じシリアル番号を「グループ化」することが重要です。
select句の列は次々に評価されるため、最初にこの行を選択することが重要です
if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,
これらの2行を選択する前に
@prev_sn := SerialNumber,
@prev_toner := Remain_Toner_Black
何故ですか?最後の2行は、現在の行の値だけを変数に割り当てます。そのため、この行で
if(@prev_toner < Remain_Toner_Black and @prev_sn = SerialNumber, 1, 0) as select_it,
変数は前の行の値を保持します。そして、ここで行うことは、「Remain_Toner_Black列の前の行の値が現在の行の値よりも小さい場合および 前の行のシリアル番号は実際の行のシリアル番号と同じで、1を返し、それ以外の場合は0を返します。 "
次に、外側のクエリで「上記が1を返したすべての行を選択してください」と簡単に言うことができます。
クエリが与えられた場合、これらすべてのサブクエリは必要ありません。それらは非常に高価で不要です。実際、それは非常に正気ではありません。クエリのこの部分では
SELECT a.ID,
a.Time,
a.SerialNumber,
a.Remain_Toner_Black,
a.Remain_Toner_Cyan,
a.Remain_Toner_Magenta,
a.Remain_Toner_Yellow,
(
SELECT COUNT(*)
FROM Reports c
WHERE c.SerialNumber = a.SerialNumber AND
c.ID <= a.ID) AS RowNumber
FROM Reports a
テーブル全体を選択します およびすべての行に対して そのグループ内の行を数えます。これは依存サブクエリです。ある種の行番号を持っているだけです。次に、これを2回実行します。これにより、これら2つの一時テーブルを結合して、前の行を取得できます。本当に、パフォーマンスがひどいのも不思議ではありません。
だから、あなたのクエリに私のソリューションを調整する方法は? Remain_Toner_Blackの前の行を取得するために使用した1つの変数の代わりに、黒、シアン、マゼンタ、および黄色の色に4つを使用します。そして、すでに行ったように、PrintersandCustomersテーブルに参加するだけです。注文を忘れないでください。