MySQL 오프셋 무한 행


114

모든 결과를 테이블에 표시하지만 테이블 시작에서 5만큼 오프셋되는 쿼리를 생성하고 싶습니다. 내가 알 수있는 한, MySQL LIMIT에는 오프셋과 제한 이 필요합니다. 이렇게 할 수있는 방법이 있습니까?


1
이것은 완전히 타당한 질문이지만 프로그래밍 방식으로 모든 것을 잡고 처음 몇 개의 레코드를 무시하는 것이 더 나은지 궁금합니다. 최선의 답인 것처럼 보이는 공포를 감안할 때 (제한 5, 18446744073709551615), MySQL의 LIMIT의 한계를 해결하는 것이 좋습니다.
— cesoid

3
@cesoid 원하는 경우 limit 5000, 18446744073709551615. 코드가 예쁘게 보이기 위해 추가로 5000 개의 행을 가져 오지는 않습니다.
— elipoultorak 2015-10-26

@ user3576887 나는 당신이 옳다고 생각합니다 .5가 훨씬 더 클 수있는 다양한 양이 아니라 (다른 사람의 문제를 해결하기보다는) 유일한 요구 사항이라는 가정하에 위의 질문을 고려했습니다.
— cesoid

나는 이것이 해결책의 추함을 받아 들일 수있는 매우 드문 작업이라고 제안한다.
— Rick James

답변:


151

LIMIT에 대한 MySQL 매뉴얼에서 :

특정 오프셋에서 결과 세트 끝까지 모든 행을 검색하려면 두 번째 매개 변수에 큰 수를 사용할 수 있습니다. 이 문은 96 번째 행에서 마지막 행까지의 모든 행을 검색합니다.

SELECT * FROM tbl LIMIT 95, 18446744073709551615;

105
무서운! MySQL이있는 그대로 Limit 절을 선택 사항으로 만들었 으면하지만 오프셋이 제공되기를 바라면서 여기에 왔습니다. 나는이 18446744073709551615가 코드 전체에 흩어져있는 것을 보았고 게으른 프로그래머를 비난했지만 디자인 기능입니다!
— Petruza

8
끔찍한 대답이지만 MySQL Doc의 공식입니다. 내가 말할 수있는 것 @ _ @
— GusDeCooL

21
18446744073709551615는 궁금해하는 사람들에게 2 ^ 64-1입니다. 이 값을 32 비트 정수로 저장할 수 없기 때문에주의해야 할 수도 있습니다. 호환성을 보장하기 위해 이것을 문자열로 저장해야합니다.
— AlicanC 2011

13
무서운! 그들은 그것보다 더 우아 해져야한다 ... Limit -1아니면 Limit Null꽤 합리적으로 보인다! 또는 제한과 같은 하위 쿼리 받아 들여야이어야select * from table limit (select count(*) from table)
— 발칸 까마귀

19
오버플로 효과를 피하기 위해 php 'PHP_INT_MAX'를 사용하십시오.
— Karl Adler

24

언급했듯이 LIMIT가 필요하므로 가능한 최대 한도 인 18446744073709551615 (부호없는 BIGINT의 최대 값)를 사용해야합니다.

SELECT * FROM somewhere LIMIT 18446744073709551610 OFFSET 5

33
와우, 이것이 MySQL 팀의 공식 솔루션입니까?
— Antony

12

다른 답변에서 언급했듯이 MySQL은 한도의 레코드 수로 18446744073709551615를 사용하도록 제안하지만 다음을 고려하십시오. 18,446,744,073,709,551,615 개의 레코드를 되찾은 경우 어떻게 하시겠습니까? 실제로 1,000,000,000 개의 레코드가 있다면 어떻게 하시겠습니까?

10 억 개 이상의 레코드를 원할 수도 있지만 내 요점은 원하는 수에 제한이 있고 18 조 미만이라는 것입니다. 안정성, 최적화 및 유용성을 위해 쿼리에 의미있는 제한을 두는 것이 좋습니다. 이렇게하면 마법처럼 보이는 숫자를 한 번도 본 적이없는 사람의 혼동을 줄일 수 있으며 한 번에 처리 할 레코드 수를 최소한 전달하는 추가 이점이 있습니다.

데이터베이스에서 18 조경의 레코드를 모두 가져와야한다면 1 억 단위로 레코드를 가져와 1,840 억 번 반복하는 것이 정말 원하는 것일 수 있습니다.


당신 말이 맞지만,이 결정을 개발자에게
— amd

@amd 좀 더 설명해 주시겠습니까? 당신이 무슨 말을 하려는지 모르겠습니다.
— cesoid

1
@cesoid 나는 그가 개발자가 내가 동의하는 비즈니스 로직을 임의로 선택해서는 안된다고 말하고 있다고 생각합니다. 고객에게 주문 목록을 반환한다고 가정 해 보겠습니다. 한 번에 백만 개 이상을 반환하지 않는 것이 완벽하게 합리적이지만 100 개로 제한하면 혼란이 발생할 수 있습니다.
— Autumn Leonard

@amd 18446744073709551615를 사용하지 않으려면 개발자가 앱의 동작을 변경해야한다고 말하는 것이 아닙니다. 클라이언트 나 인터페이스 디자이너가 무엇이든 구현할 때 해당 번호를 사용하는 것이 합리적 일지 고려해야한다는 것입니다. 요청했으며 어떤 것에 대해서도 올바른 구현이 될 가능성이 거의 없습니다. MySQL을 사용하기로 한 결정은 이미 개발자가 18 조 이상이 될 것인지 묻지 않고 내린 것입니다.
— cesoid

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 매뉴얼에서. 이를 달성하기 위해 unsigned 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 테이블에서 엄청난 양의 데이터 (백만 개 이상의 행)를 얻는 가장 좋은 방법에 대해 읽었습니다. 한 가지 방법은 제안 된대로 오프셋과 반환 할 마지막 행을 사용 LIMIT x,y하는 것 x입니다 y. 그러나 내가 알아 냈 듯이 그렇게하는 가장 효율적인 방법은 아닙니다. 자동 증가 열이있는 경우 시작할 레코드를 SELECT나타내는 WHERE절이 있는 문을 쉽게 사용할 수 있습니다 .

예를 들면 SELECT * FROM table_name WHERE id > x;

mysql은 사용할 때 모든 결과를 얻은 LIMIT다음 오프셋에 맞는 레코드 만 표시합니다. 성능에 가장 적합하지 않습니다.

출처 :이 질문에 대한 답변 MySQL Forums . 질문은 6 년 정도 된 것입니다.


13
레코드를 삭제 한 적이있는 경우 잘못된 결과를 제공합니다. 이 방법은 대부분의 경우 작동하고 작동하지 않으면 조용히 실패하기 때문에 특히 위험합니다.
— 10

0

LIMIT와 함께 MySQL 문을 사용할 수 있습니다.

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;

그런 다음 내 제한으로 카운트에서 얻은 결과를 사용하여 쿼리를 작성합니다 (테이블이 반환 할 수있는 최대 행 수이기 때문에). 다음과 같은 것 :

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
7M 레코드가있는 테이블에서 select count (*)는 약 17 초가 걸립니다
— amd

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

id는 자동 증가 또는 고유 한 숫자 열이 될 수 있습니다.


7
나쁜 생각. 행을 삭제 한 적이 있으면 잘못된 오프셋을 제공합니다.
— 10
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.