Я хотел бы создать запрос, который отображает все результаты в таблице, но смещен на 5 от начала таблицы. Насколько я могу судить, MySQL LIMIT требует не только смещения, но и ограничения. Есть какой-либо способ сделать это?
@cesoid, а если вам нужен limit 5000, 18446744073709551615. Вы не собираетесь извлекать лишние 5000 строк только для того, чтобы ваш код выглядел красиво.
@ user3576887 Я думаю, что вы правы, я просто рассматривал вопрос выше, предполагая, что 5 является единственным требованием, а не какой-то переменной суммой, которая может быть намного больше (и вместо решения чьей-то проблемы).
Я предполагаю, что это настолько редкая задача, что можно смириться с безобразием решения.






Как вы упомянули, требуется LIMIT, поэтому вам нужно использовать максимально возможный предел, который составляет 18446744073709551615 (максимум беззнакового BIGINT)
SELECT * FROM somewhere LIMIT 18446744073709551610 OFFSET 5
Вау, это официальное решение от команды MySQL?
Интересно, почему люди до сих пор используют MySQL, когда есть PostgreSQL ...
Из Руководство MySQL по LIMIT:
To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:
SELECT * FROM tbl LIMIT 95, 18446744073709551615;
Ужасный! Я пришел сюда в надежде, что MySQL сделал предложение Limit необязательным, как есть, но также с предоставленным смещением ... но нет! Я видел этот разброс 18446744073709551615 по всему коду и обвинял ленивых программистов, но это особенность дизайна!
ужасный ответ, но это официальный документ из MySQL Doc. Что я могу сказать @_@
18446744073709551615 - это 2 ^ 64-1 для тех, кому интересно. Вы можете быть осторожны, потому что вы не сможете сохранить это значение в виде 32-битного целого числа. Вы должны убедиться, что сохранили это как строку, чтобы обеспечить совместимость.
Ужасный! они должны быть более элегантными, чем это ... Limit -1 или Limit Null выглядят довольно разумно! или, по крайней мере, Limit должен принимать подзапрос типа select * from table limit (select count(*) from table)
что я могу сказать .. я разочарован! это просто грязный обходной путь, и все же это единственный вариант :( Команда MySQL должна это исправить!
используйте php 'PHP_INT_MAX', чтобы избежать эффектов переполнения.
Я думаю, что это подпадает под категорию TODINAWYW, которую я только что придумал, и означает «Официальная документация - это не всегда то, что вам нужно». В нем объясняется, как вы могли бы получить все записи, если бы у вас была таблица, которая была заполнена до (примерно) 18 квинтиллионов строк, а также предлагалось использовать «некоторое большое число» в качестве альтернативы, но я бы предположил, что существует значимая, не- бесконечное и отличное от 18 квинтиллионов количество записей, которые вы хотите вернуть, и вы должны это использовать. (Я включил это в свой ответ.)
Похоже, что в MySQL есть некоторая особая обработка для 18446744073709551615. Это не принято в качестве LIMIT для предложения DELETE с включенным безопасным режимом, например. Однако 18446744073709551614 принимается.
Это нелепо! Интересно, почему люди до сих пор используют MySQL, когда есть PostgreSQL ...
Другой подход - выбрать столбец с автоимкрементом, а затем отфильтровать его с помощью HAVING.
SET @a := 0;
select @a:=@a + 1 AS counter, table.* FROM table
HAVING counter > 4
Но я бы, вероятно, придерживался подхода высоких лимитов.
спасибо, и мне интересно, как я могу поместить такой запрос в оператор PHP! я имею в виду именно так $sql = 'SET @a :=0 SELECT .....';
Как раз сегодня я читал о том, как лучше всего получить огромные объемы данных (более миллиона строк) из таблицы mysql. Один из способов - использовать LIMIT x,y, где x - это смещение, а y - последняя строка, которую вы хотите вернуть. Однако, как я выяснил, это не самый эффективный способ сделать это. Если у вас есть столбец с автоинкрементом, вы можете легко использовать оператор SELECT с предложением WHERE, указывающим, с какой записи вы хотите начать.
Например,
SELECT * FROM table_name WHERE id > x;
Кажется, что mysql получает все результаты, когда вы используете LIMIT, а затем показывает только те записи, которые соответствуют смещению: не самое лучшее для производительности.
Источник: Ответ на этот вопрос Форумы MySQL. Сразу обратите внимание, вопрос примерно 6 лет.
Это даст неверные результаты, если вы когда-либо удаляли запись. Этот метод особенно опасен, потому что он работает большую часть времени и тихо дает сбой, когда он не работает.
Я знаю, что это старый, но я не видел аналогичного ответа, поэтому я бы использовал это решение.
Во-первых, я бы выполнил запрос количества в таблице, чтобы увидеть, сколько записей существует. Этот запрос выполняется быстро и обычно время выполнения незначительно. Что-то типа:
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, чтобы получить фактическое точное значение, которое будет использоваться в качестве предела. Передача значения «18446744073709551610» просто не имеет смысла, если я действительно могу определить подходящий предел для предоставления.
select count (*) в таблице с 7M записями занимает около 17 секунд
WHERE .... AND id > <YOUROFFSET>
id может быть любым автоматически увеличивающимся или уникальным числовым столбцом, который у вас есть ...
Плохая идея. Это даст неправильное смещение, если вы когда-либо удаляли строку.
Вы можете использовать оператор 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: «select count (*) в таблице с 7M записями занимает около 17 секунд»
Как отмечалось в других ответах, MySQL предлагает использовать 18446744073709551615 в качестве количества записей в пределе, но учтите следующее: что бы вы сделали, если бы получили обратно 18 446 744 073 709 551 615 записей? Фактически, что бы вы сделали, если бы у вас было 1 000 000 000 записей?
Может быть, вам действительно нужно более одного миллиарда записей, но я хочу сказать, что есть некоторый предел на число хочу, и оно меньше 18 квинтиллионов. Ради стабильности, оптимизации и, возможно, удобства использования, я бы предложил установить некоторые значимые ограничения на запрос. Это также уменьшит путаницу для тех, кто никогда не видел это волшебное число, и получит дополнительное преимущество в виде сообщения, по крайней мере, о том, сколько записей вы готовы обрабатывать одновременно.
Если вам действительно нужно получить все 18 квинтиллионов записей из вашей базы данных, возможно, вы действительно хотите получить их с шагом 100 миллионов и выполнить цикл 184 миллиарда раз.
Вы правы, но оставлять это решение разработчику - не лучший выбор.
@amd Не могли бы вы объяснить это поподробнее? Я не знаю, что вы пытаетесь сказать.
@cesoid Я думаю, он говорит, что разработчики не должны произвольно выбирать бизнес-логику, с чем я согласен, но только до определенной степени. Допустим, вы возвращаете клиенту список заказов. Совершенно разумно никогда не возвращать больше, скажем, миллиона за раз, но ограничение до 100 может вызвать путаницу.
@amd Я не говорю, что разработчик должен изменить поведение приложения, чтобы избежать использования 18446744073709551615. Я говорю, что им следует подумать, имеет ли смысл использовать это число как часть реализации того, что клиент или дизайнер интерфейса запросил, и вряд ли это будет правильная реализация для чего-либо. Решение использовать MySQL, вероятно, уже было принято разработчиком, не задаваясь вопросом, будет ли что-то более 18 квинтиллионов.
Как уже упоминалось, из руководства MySQL. Для этого вы можете использовать максимальное значение беззнакового большого int, то есть это ужасное число (18446744073709551615). Но чтобы сделать его немного менее беспорядочным, вы можете использовать побитовый оператор тильды "~".
LIMIT 95, ~0
он работает как побитовое отрицание. Результат «~ 0»: 18446744073709551615.
Не работает в MariaDB 10.3 :( Я пробовал и LIMIT 5, ~0, и LIMIT ~0 OFFSET 5. Это функция MySQL 8.0?
В MySQL 5.7 этого нет - неверный синтаксис.
Это совершенно правильный вопрос, но мне интересно, что было бы лучше - захватить все и программно проигнорировать первые несколько записей. Учитывая ужас того, что кажется лучшим ответом (предел 5, 18446744073709551615), я бы в значительной степени поддержал работу над ограничениями MySQL LIMIT.