MySQLオフセット無限行


114

すべての結果をテーブルに表示するが、テーブルの先頭から5だけオフセットされているクエリを作成したいと思います。私の知る限り、MySQLにLIMITはオフセットと同様に制限が必要です。これを行う方法はありますか?


1
これは完全に有効な質問ですが、すべてを取得し、プログラムで最初のいくつかのレコードを無視する方が良いのではないかと思います。最善の答えであると思われる恐怖(制限5、18446744073709551615)を考慮して、MySQLの制限の制限に対処することを強くお勧めします。
cesoid 2015年

3
@cesoid必要に応じてlimit 5000, 18446744073709551615。コードをきれいに見せるためだけに、追加の5000行をフェッチすることはありません。
elipoultorak 2015年

@ user3576887私はあなたが正しいと思います、私は上記の質問を検討したところ、5が唯一の要件であり、はるかに大きくなる可能性のある変動量ではなく(そして他の誰かの問題を解決するのではなく)と仮定しました。
cesoid 2015年

これは非常にまれな作業であるため、ソリューションの醜さを受け入れることができます。
リックジェームズ

回答:


151

LIMIT上のMySQLのマニュアル

特定のオフセットから結果セットの最後までのすべての行を取得するには、2番目のパラメーターに大きな数を使用できます。次のステートメントは、96行目から最後のすべての行を取得します。

SELECT * FROM tbl LIMIT 95, 18446744073709551615;

105
ひどい!MySQLがLimit句をオプションであるように、またオフセットを指定してオプションにしたことを期待してここに来ました...しかし、いいえ!この18446744073709551615がコード全体に散らばっているのを見たので、怠惰なプログラマーを非難していましたが、これは設計上の特徴です!
ペトルザ

8
完全な答えですが、それはMySQL Docからの公式です。@ _ @で言えること
GusDeCooL '19年

21
18446744073709551615は、疑問に思っていた人にとって2 ^ 64-1です。この値を32ビット整数に格納することはできないため、注意が必要な場合があります。互換性を確保するために、これを文字列として保存する必要があります。
AlicanC 2011

13
ひどい!彼らはそれよりもエレガントにする必要があります... Limit -1またはLimit Nullかなり合理的に見えます!または少なくともLimitは次のようなサブクエリを受け入れる必要がありますselect * from table limit (select count(*) from table)
vulcan raven

19
php 'PHP_INT_MAX'を使用して、オーバーフローの影響を回避します。
Karl Adler

24

あなたが言及したように、それはLIMITが必要なので、可能な限り最大の制限である18446744073709551615(符号なしBIGINTの最大値)を使用する必要があります。

SELECT * FROM somewhere LIMIT 18446744073709551610 OFFSET 5

33
うわー、これはMySQLチームの公式ソリューションですか?
アントニー

12

他の回答で述べたように、MySQLは制限内のレコード数として18446744073709551615を使用することを推奨していますが、これを考慮してください。実際、1,000,000,000件のレコードを取得したらどうしますか?

10億以上のレコードが必要な場合もありますが、私の指摘では、必要な数には制限があり、18兆未満です。安定性、最適化、そしておそらく使いやすさのために、クエリに意味のある制限を設けることをお勧めします。これにより、その魔法のような数を見たことがない人の混乱も減り、少なくとも一度に処理するレコード数を伝えるという追加の利点があります。

データベースから18兆のレコードをすべて取得する必要がある場合、1億単位でそれらを取得し、1840億回ループすることが本当に必要な場合があります。


あなたは正しいですが、開発者にこの決定を続けることは良い選択ではありません
amd

@amdそれについてもう少し説明してもらえますか?あなたが何を言おうとしているのか分かりません。
セソイド

1
@cesoid彼は、私が同意するビジネスロジックを任意に選択するのは開発者であってはならないと彼は言っていると思います。注文のリストを顧客に返すとします。たとえば、一度に100万を超える値を返さないことは完全に合理的ですが、100に制限すると混乱が生じる可能性があります。
秋のレナード

@amd 18446744073709551615の使用を回避するために、開発者がアプリの動作を変更する必要があると言っているのではありません。その数値を使用することが、クライアントまたはインターフェースデザイナーの実装の一部として意味があるかどうかを検討する必要があると言っていますが要求し、それが何にでも適切な実装になる可能性は非常に低いです。MySQLを使用するという決定は、おそらく開発者がすでに18兆を超えるものがあるかどうかを尋ねることなく行われたものです。
セソイド

5

別のアプローチは、自動インクリメントされた列を選択し、HAVINGを使用してそれをフィルタリングすることです。

SET @a := 0; 
select @a:=@a + 1 AS counter, table.* FROM table 
HAVING counter > 4

しかし、私はおそらく上限のアプローチに固執するでしょう。


ありがとう、そしてそのようなクエリをどのようにPHPステートメントに入れることができるのだろう!私はそのように意味します$sql = 'SET @a :=0 SELECT .....';
Reham Fahmy

2

他の人が述べたように、MySQLマニュアルから。これを実現するために、符号なしbig intの最大値、つまりこのひどい数値(18446744073709551615)を使用できます。しかし、少し面倒を少なくするために、チルド "〜"ビット演算子を使用できます。

  LIMIT 95, ~0

ビット単位の否定として機能します。「〜0」の結果は18446744073709551615です。


1
MariaDB 10.3で動作しません:(私は両方を試してみましたLIMIT 5, ~0し、LIMIT ~0 OFFSET 5これは、MySQL 8.0の機能です。?
jurchiksは

1
これはMySQL 5.7のものではありません-無効な構文です。
Jonny Nott

0

ちょうど今日、mysqlテーブルから膨大な量のデータ(100万行以上)を取得する最良の方法について読んでいました。提案されているように、1つの方法は、LIMIT x,ywhere を使用しxて、オフセットとy、返される最後の行を指定することです。しかし、私が知ったように、それはそうするための最も効率的な方法ではありません。自動インクリメント列がある場合は、どのレコードから開始するかSELECTを指定するWHERE句を含むステートメントを簡単に使用できます。

例えば、 SELECT * FROM table_name WHERE id > x;

mysqlは使用時にすべての結果を取得LIMITし、オフセットに収まるレコードのみを表示するようです。パフォーマンスには最適ではありません。

出典:この質問への回答MySQLフォーラム。注意してください、質問は約6歳です。


13
これまでにレコードを削除したことがある場合、これは誤った結果をもたらします。この方法はほとんどの場合機能するため、特に危険であり、機能しない場合は警告なしで失敗します。
オクターブ2014

0

MySQLステートメントをLIMITで使用できます。

START TRANSACTION;
SET @my_offset = 5;
SET @rows = (SELECT COUNT(*) FROM my_table);
PREPARE statement FROM 'SELECT * FROM my_table LIMIT ? OFFSET ?';
EXECUTE statement USING @rows, @my_offset;
COMMIT;

MySQL 5.5.44でテスト済み。したがって、18446744073709551615という番号の挿入を回避できます。

注:トランザクションは、変数@rowsがステートメントの実行で考慮されるテーブルと一致していることを確認します。


@amdが述べたように:「7Mレコードのテーブルでselect count(*)は約17

-1

これは古いことはわかっていますが、同様の応答が見られなかったので、これが私が使用するソリューションです。

まず、テーブルでカウントクエリを実行して、レコードの数を確認します。このクエリは高速で、通常、実行時間はごくわずかです。何かのようなもの:

SELECT COUNT(*) FROM table_name;

次に、countから取得した結果を制限として使用してクエリを作成します(これは、テーブルが返す可能性のある最大行数であるため)。何かのようなもの:

SELECT * FROM table_name LIMIT count_result OFFSET desired_offset;

またはおそらく次のようなもの:

SELECT * FROM table_name LIMIT desired_offset, count_result;

もちろん、必要に応じて、count_resultからdesired_offsetを差し引いて、実際の正確な値を取得し、制限として指定できます。提供する適切な制限を実際に決定できる場合、「18446744073709551610」の値を渡しても意味がありません。


2
700万レコードのテーブルでselect count(*)を実行すると約17秒かかる
amd

-7
WHERE .... AND id > <YOUROFFSET>

idは、自動インクリメントまたは一意の数値列にすることができます...


7
悪いアイデア。行を削除したことがある場合、誤ったオフセットが表示されます。
オクターブ2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.