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.