3

私は、そのパネルにさまざまなクエリを送信できる汎用データ パネルを使用しています。テーブルまたはビューから選択する単純なクエリの場合もあれば、ユーザーが複雑な結合やその他の式を使用して独自に定義する複雑なクエリの場合もあります。データ パネルを変更して、ユーザーがレコードを選択してからテーブルを並べ替えた場合に、レコードが現在表示されているページを見つけてそこに移動し、レコードを再選択できるようにしようとしています。

移動先のページ番号を見つけるのに問題があることを除いて、これでほとんど解決しました。最初は単純にデータ パネルの行をループしていましたが、ページングが原因で、ページ番号が大きくなるほど非効率的であることがわかりました。代わりに、SQL を介して直接これを行うことにしましたが、これが今行き詰まっています。

結果を生成したのと同じクエリを実行して、選択した行の行番号を見つけることができれば、移動してそのページに直接ジャンプする必要がある最終ページ番号を計算できると判断しました。結果を生成するために実行されたクエリを取得し、変数をインクリメントして行番号を取得しました。

元のクエリは

select *
from table_a
order by column_c desc

そして、行番号を持つ変更されたクエリは次のようになりました

select *, (@rownum := @rownum + 1) as rownum
from
(select @rownum := 0) rn
, (
  select *
  from table_a
  order by column_c desc
) data

この時点で、すべてのレコードを選択しています。次に、上記のクエリをラップし、レコードが選択したレコードと一致する最小の行を選択しました

select min(rownum)
from
(  
  select *, (@rownum := @rownum + 1) as rownum
  from
  (select @rownum := 0) rn
  , (
    select *
    from table_a
    order by column_c desc
  ) data
) wrapper
where
  primarykeyfield1 = ?
  and primarykeyfield2 = ?

最初はこれが機能しているように見えました。しかし、テスト中に、十分に一意でないフィールド (たとえば、1000 レコードすべてがこのフィールドで同じ値を持つ) でソートすると、機能しなくなることがわかりました。掘り下げてみたところ、クエリが実行されるたびに上記のコードが異なるrownumを返すことがわかりました。

さらに掘り下げた後、次のクエリを実行すると、必要な結果が得られることがわかりました

select * from table_a order by column_c

しかし、単にそのクエリをそのようにラップした場合

select * from (select * from table_a order by column_c)

クエリを実行するたびに、レコードの順序が大幅に変更されました。これは、実際に変更されているため、行番号が変更された理由を説明しています。ただし、クエリをラップするだけで順序が変わる理由がわかりません。私はこれを他のデータベースエンジンで行ったので、特にMySqlに関係していると思いますが、理由を説明する情報を見つけることができませんでした. 私の推測では、このようなクエリでラップされたときに order by が適用されないか、動作が期待どおりではありません。

次に、次のようにrownumカウントをメイン/ベースクエリに直接移動しようとしました

select *, (@rownum := @rownum + 1) as rownum
from (select @rownum := 0) rn, table_a
order by column_c desc

このクエリを単独で実行すると、正しい行番号が作成されます。ただし、選択したレコードの特定の行番号を見つける必要があるため、そのクエリを次のようにラップする必要があります

select min(rownum)
from (
  select *, (@rownum := @rownum + 1) as rownum
  from (select @rownum := 0) rn, table_a
  order by column_c desc
) data
where
  primarykeyfield1 = ?
  and primarykeyfield2 = ?

これを行うとすぐに、順序は無視されているように見え、ベースクエリの順序ではなく、レコードがテーブルに表示される順序でカウントされます。

まとめたときにデータセットの並べ替えが正しく適用されないという根本的な問題と、特定のレコードが存在するページ番号を見つけるための他の解決策の両方を理解することに興味があります。

最終的にユーザーは複数の行を選択する可能性があり、それらの行はすべて最後の where 句に入る可能性があるため、最後の外部クエリで min を使用していることに注意してください。だから、一番下の行番号を見つけて、そのページに移動したいのです。

4

3 に答える 3

0

Reza Mamun に感謝します。 limit を使用してデータを取得した場合でも、レコードがどの番号に対応するかを正確に知ることができるように、レコード番号を配置する方法を考案しました。

SELECT @rownum:=@rownum + 1 AS myRowSerial,
*
FROM myTable, (SELECT @rownum:=0) AS nothingButSetInitialValue
LIMIT 0,10

これにより、記録的な数字が得られます。制限を実装するには、たとえば、同じ制限を渡しLIMIT 10,10、rownumを制限の開始に設定します。つまり10FROM句で

limit の変更されたクエリは次のようになります。

SELECT @rownum:=@rownum + 1 AS myRowSerial,
*
FROM myTable, (SELECT @rownum:=10) AS nothingButSetInitialValue
LIMIT 10,10

次に、次の一連のレコードは次のようになります。

SELECT @rownum:=@rownum + 1 AS myRowSerial,
*
FROM myTable, (SELECT @rownum:=20) AS nothingButSetInitialValue
LIMIT 20,10

もう一度ありがとう、これは本当に私の日を救った!! :)

GROUP BY**更新:**クエリに句がある場合、これは機能しません。

于 2014-05-30T11:12:28.483 に答える