복붙노트

[SQL] 마이크로 소프트 SQL 서버 2000 에뮬레이션 MySQL의 LIMIT 절

SQL

마이크로 소프트 SQL 서버 2000 에뮬레이션 MySQL의 LIMIT 절

내가 젠드 프레임 워크의 데이터베이스 구성 요소에서 일 때, 우리는 추상적으로 MySQL은, PostgreSQL을, 그리고 SQLite는 지원하는 LIMIT 절의 기능을 시도했다. 즉, 쿼리를 작성하면이 방법을 수행 할 수 있습니다 :

$select = $db->select();
$select->from('mytable');
$select->order('somecolumn');
$select->limit(10, 20);

데이터베이스가 LIMIT를 지원하는 경우, 이것은 다음과 같은 SQL 쿼리를 생성합니다

SELECT * FROM mytable ORDER BY somecolumn LIMIT 10, 20

이것은 (절 그런데, 표준 SQL 언어의 일부가 아닌 것을) LIMIT를 지원하지 않는 데이터베이스의 브랜드를 더 복잡했다. 당신이 행 번호를 생성 할 경우, 전체 쿼리 파생 테이블을 만들고, BETWEEN 외부 쿼리를 사용한다. 이것은 오라클과 IBM DB2를위한 솔루션이다. 하나는 쿼리이 방법을 쓸 수 있도록 마이크로 소프트 SQL 서버 2005, 유사한 행 번호 기능을 가지고 있습니다 :

SELECT z2.*
FROM (
    SELECT ROW_NUMBER OVER(ORDER BY id) AS zend_db_rownum, z1.*
    FROM ( ...original SQL query... ) z1
) z2
WHERE z2.zend_db_rownum BETWEEN @offset+1 AND @offset+@count;

그러나 Microsoft SQL 서버 2000는 ROW_NUMBER () 함수를 가지고 있지 않습니다.

내 질문은 그래서, 당신은 전적으로 SQL을 사용하여 Microsoft SQL 서버 2000의 LIMIT 기능을 에뮬레이트 할 수있는 방법을 마련 할 수 있습니까? 커서 나 T-SQL 또는 저장 프로 시저를 사용하지 않고. 그것은 LIMIT, 모두 수 및 오프셋 모두 인수를 지원한다. 임시 테이블을 사용하여 솔루션도 허용되지 않습니다.

편집하다:

MS SQL Server 2000의 가장 일반적인 솔루션은 예를 들어 75을 통해 행 (50)를 얻을 수 있도록, 아래와 같은 것 같다 :

SELECT TOP 25 *
FROM ( 
  SELECT TOP 75 *
  FROM   table 
  ORDER BY BY field ASC
) a 
ORDER BY field DESC;

그러나, 이것은 전체 결과 집합 인 경우, 60 개 행을 말할 작동하지 않습니다. 내부 쿼리 반환 60 행으로 인해 50-75의 원하는 "페이지"에 맞지 않는 그런 다음 상단 (75) 외부 쿼리 반환 행 35-60에서 그의. 당신은 페이지 크기의 배수 될 일이없는 결과 세트의 마지막 "페이지"를 필요로하지 않는 한 기본적으로,이 솔루션은 작동합니다.

편집하다:

또 다른 해결책은 잘 작동하지만 결과 집합을 가정 할 수있는 경우에만 고유 한 열을 포함 :

SELECT TOP n *
FROM tablename
WHERE key NOT IN (
    SELECT TOP x key
    FROM tablename
    ORDER BY key
);

결론:

없음 범용 솔루션은 MS SQL Server 2005의 ROW_NUMBER () 함수를 사용할 수있는 경우에 존재하는 MS SQL 서버 2000 좋은 솔루션에 LIMIT을 모방 위해 존재하는 것 같다.

해결법

  1. ==============================

    1.여기가 문을 제외하고 사용하기 때문에 단지는 SQL Server 2005에서 작동하고 새로운 또 다른 솔루션입니다. 하지만 어쨌든 공유 할 수 있습니다. 당신은 기록 50 얻고 싶다면 - 75 쓰기 :

    여기가 문을 제외하고 사용하기 때문에 단지는 SQL Server 2005에서 작동하고 새로운 또 다른 솔루션입니다. 하지만 어쨌든 공유 할 수 있습니다. 당신은 기록 50 얻고 싶다면 - 75 쓰기 :

    select * from (
        SELECT top 75 COL1, COL2
        FROM MYTABLE order by COL3
    ) as foo
    except
    select * from (
        SELECT top 50 COL1, COL2
        FROM MYTABLE order by COL3
    ) as bar
    
  2. ==============================

    2.

    SELECT TOP n *
    FROM tablename
    WHERE key NOT IN (
        SELECT TOP x key
        FROM tablename
        ORDER BY key
        DESC
    );
    
  3. ==============================

    3.당신은 단지 LIMIT 필요로 할 때 그 명확하게 알 수 있도록, MS SQL은 해당 TOP 키워드를 가지고있다. 당신이 OFFSET와 LIMIT를 필요로 할 때, 당신은 이전에 설명한 같은 몇 가지 해킹을 시도 할 수 있지만, 그들은 모두 한 가지 방법을 주문하는 오버 헤드, 즉를 추가 한 다음 다른, 또는 expencive 작동하지 않는. 나는 모든 폭포는 필요하지 않습니다 생각합니다. 내 oppinion에서 가장 깨끗한 해결책은 바로 SQL 측에 오프셋없이 TOP을 사용하고 PHP에서 mssql_data_seek처럼, 해당 클라이언트 방식으로 필요한 시작하는 레코드를 찾는 것입니다. 이것은 순수한 SQL 솔루션 아니지만, 나는 그것이 (오버 헤드를 추가하지 않습니다 때문에 그것이 최선의 하나라고 생각 스킵 오버 당신이 그들을지나 추구 할 때 기록 즉 경우 어떻게 당신을 걱정 네트워크에 전송되지 않습니다 ).

    당신은 단지 LIMIT 필요로 할 때 그 명확하게 알 수 있도록, MS SQL은 해당 TOP 키워드를 가지고있다. 당신이 OFFSET와 LIMIT를 필요로 할 때, 당신은 이전에 설명한 같은 몇 가지 해킹을 시도 할 수 있지만, 그들은 모두 한 가지 방법을 주문하는 오버 헤드, 즉를 추가 한 다음 다른, 또는 expencive 작동하지 않는. 나는 모든 폭포는 필요하지 않습니다 생각합니다. 내 oppinion에서 가장 깨끗한 해결책은 바로 SQL 측에 오프셋없이 TOP을 사용하고 PHP에서 mssql_data_seek처럼, 해당 클라이언트 방식으로 필요한 시작하는 레코드를 찾는 것입니다. 이것은 순수한 SQL 솔루션 아니지만, 나는 그것이 (오버 헤드를 추가하지 않습니다 때문에 그것이 최선의 하나라고 생각 스킵 오버 당신이 그들을지나 추구 할 때 기록 즉 경우 어떻게 당신을 걱정 네트워크에 전송되지 않습니다 ).

  4. ==============================

    4.거기 아주 간단합니다 나는 내 ORM이 구현하려고합니다. 정말 SQL 서버에 있어야한다면 나는 SQL 문에 다음과 같은 LINQ에 대한 SQL에 LINQ에 의해 생성 된 코드를보고 거기에서 갈 것입니다. 그 코드를 구현 MSFT 엔지니어는 수년 동안 SQL 팀의 일원이었고, 그가 무엇을하고 있었는지 알고 있었다.

    거기 아주 간단합니다 나는 내 ORM이 구현하려고합니다. 정말 SQL 서버에 있어야한다면 나는 SQL 문에 다음과 같은 LINQ에 대한 SQL에 LINQ에 의해 생성 된 코드를보고 거기에서 갈 것입니다. 그 코드를 구현 MSFT 엔지니어는 수년 동안 SQL 팀의 일원이었고, 그가 무엇을하고 있었는지 알고 있었다.

    VAR 결과 = myDataContext.mytable.Skip (pageIndex * pageSize가) .Take (pageSize가)

  5. from https://stackoverflow.com/questions/216673/emulate-mysql-limit-clause-in-microsoft-sql-server-2000 by cc-by-sa and MIT license