AD JB Toolbox 01

MariaDB 강좌 / ORDER BY·LIMIT로 정렬하고 조회 범위 제한하기

ORDER BY는 조회 행의 순서를 정하고 LIMIT는 그 순서에서 가져올 행 수와 시작 위치를 제한합니다. 같은 가격처럼 정렬값이 중복되면 기본키를 보조 정렬 기준으로 추가해야 상위 목록과 페이지 경계를 일관되게 설명할 수 있습니다.

정렬 기준과 가져올 개수를 따로 정하기

가격이 높은 상품 세 개를 고른다면 가격 내림차순과 세 행 제한이 모두 필요합니다. LIMIT 3만 적으면 서버가 어떤 세 행을 먼저 반환할지 업무상 순서가 보장되지 않습니다. 정렬은 원본 행의 저장 위치를 재배치하는 작업이 아니라 조회 결과의 순서를 정하는 작업입니다. 정렬 전에 남길 행은 WHERE로 조건 지정하기: 비교·AND·OR·IN·BETWEEN·LIKE로 정합니다. 조회 결과의 의미를 유지하며 깊은 페이지 비용을 검토하는 과정은 조회 조건·정렬·페이지 나누기를 개선하기에서 같은 기준으로 확장합니다.

표현 뜻 이 예제의 사용
ASC 오름차순·기본 방향 같은 가격에서 번호 작은 순
DESC 내림차순 가격 높은 순
LIMIT 3 최대 3행 상위 상품 세 개
LIMIT 2 OFFSET 2 앞의 2행을 건너뛰고 최대 2행 두 번째 페이지

각 정렬 열마다 방향을 지정합니다. ORDER BY price DESC, product_id ASC에서 DESC가 두 열 모두에 적용되는 것은 아닙니다. 숫자처럼 보이는 문자열을 정렬하면 숫자 열과 순서가 달라질 수 있으므로 타입도 확인합니다.

같은 가격이 있는 상품 데이터 만들기

명령줄 클라이언트에서 course_user로 학습용 서버에 접속하고 shopcourse 데이터베이스를 준비합니다. 접속과 UTF-8 SQL 파일 실행 방법은 명령줄 클라이언트와 SQL 파일 실행 안내를 참고하세요. 아래 코드는 운영 서버가 아닌 연습 환경에서 실행합니다.

이 글은 products_17_lab이라는 독립된 실습 테이블을 사용합니다. 이전 강좌의 products 등 기존 테이블에는 손대지 않습니다. SELECT VERSION(), DATABASE();와 SHOW TABLES LIKE 'products_17_lab';로 서버·선택한 데이터베이스·이름 중복을 먼저 확인합니다. 같은 이름이 이미 있으면 정의와 데이터를 확인하고, 이 글에서 만든 연습 데이터인지 판단한 뒤 마지막 절의 반복 방법을 따르세요.

USE shopcourse;
CREATE TABLE products_17_lab (
  product_id INT NOT NULL AUTO_INCREMENT,
  product_name VARCHAR(100) NOT NULL,
  category VARCHAR(30) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL DEFAULT 0,
  note VARCHAR(100) NULL DEFAULT NULL,
  PRIMARY KEY (product_id),
  CONSTRAINT ck_p17_price CHECK (price >= 0),
  CONSTRAINT ck_p17_stock CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO products_17_lab
  (product_id, product_name, category, price, stock, note)
VALUES (1, '노트', '문구', 3500.00, 20, NULL),
  (2, '볼펜', '문구', 1500.00, 0, ''),
  (3, '머그컵', '생활', 8000.00, 12, '선물 포장'),
  (4, '스탠드', '생활', 25000.00, 5, NULL),
  (5, '파일', '문구', 1500.00, 50, ''),
  (6, '케이블', '전자', 8000.00, 0, '호환 확인');

3번 머그컵과 6번 케이블은 8000원, 2번 볼펜과 5번 파일은 1500원입니다. 같은 가격일 때의 순서가 페이지 결과에 영향을 주는 상황을 일부러 만든 것입니다. 기본키 product_id는 각 행마다 다르므로 최종 동점 해소 기준으로 사용할 수 있습니다.

가격 내림차순에 기본키 보조 기준 붙이기

SELECT product_id, product_name, price FROM products_17_lab
ORDER BY price DESC, product_id ASC LIMIT 3;
반환 순서 번호 상품 가격
1 4 스탠드 25000.00
2 3 머그컵 8000.00
3 6 케이블 8000.00

정렬은 첫 기준 price를 비교하고, 값이 같을 때만 다음 기준 product_id를 비교합니다. product_id 방향을 DESC로 바꾸면 같은 가격의 6번이 3번보다 먼저 옵니다. 다시 ASC로 되돌려 결과를 비교하세요. 가격이 모두 다르다고 가정해 보조 기준을 빼면 이후 데이터가 추가되었을 때 순서가 불안정해질 수 있습니다. ORDER BY 공식 문서에서 여러 정렬식의 적용 순서를 확인할 수 있습니다.

OFFSET 페이지와 그 한계 확인하기

SELECT product_id, price FROM products_17_lab
ORDER BY price DESC, product_id ASC LIMIT 2 OFFSET 0;
SELECT product_id, price FROM products_17_lab
ORDER BY price DESC, product_id ASC LIMIT 2 OFFSET 2;

첫 페이지의 번호는 4·3, 다음 페이지는 6·1입니다. OFFSET은 페이지 번호가 아니라 건너뛸 행 수이며, 페이지 크기가 2라면 세 번째 페이지의 OFFSET은 4입니다. 같은 의미로 LIMIT 2, 2를 쓸 수 있지만 두 인수의 역할이 혼동되면 LIMIT 개수 OFFSET 시작위치 형태를 쓰는 편이 명확합니다.

일관된 보조 정렬을 해도 두 요청 사이에 다른 연결이 행을 추가·삭제하거나 가격을 바꾸면 페이지 경계가 달라질 수 있습니다. OFFSET은 같은 데이터 집합이라는 전제에서 위치를 설명합니다. 매우 큰 OFFSET은 앞부분의 많은 행을 처리하게 될 수 있어 깊은 페이지에서 비용도 검토해야 합니다. LIMIT가 항상 정렬·검색 작업 전체를 그 개수만큼으로 줄인다는 뜻은 아닙니다. LIMIT 공식 문서에서 시작 위치와 개수의 의미를 확인하세요.

마지막 정렬값을 기억하는 조회와 NULL 순서

앞 페이지의 마지막 행이 가격 8000·번호 3인 상황에서는 그 뒤로 올 조건을 정해 조회할 수도 있습니다. 내림차순 가격이 더 작거나, 같은 가격에서 번호가 더 큰 행이 뒤에 옵니다. 이 조건은 현재 데이터와 두 가지 정렬 방향에 맞춘 것이므로 정렬을 바꾸면 함께 바꿔야 합니다.

SELECT product_id, price FROM products_17_lab
WHERE price < 8000 OR (price = 8000 AND product_id > 3)
ORDER BY price DESC, product_id ASC LIMIT 2;

결과는 번호 6·1로 OFFSET 2의 예제와 같습니다. 이 방식을 키셋 페이지 나누기라고 부르며, 다음 조회를 위한 마지막 값을 보관해야 합니다. 임의의 페이지 번호로 바로 건너뛰는 기능과는 요구 사항이 다릅니다. 동시 수정 중 완전한 고정 목록이 필요하면 스냅샷이나 데이터 정책까지 검토해야 합니다.

SELECT product_id, note FROM products_17_lab
ORDER BY note IS NULL ASC, note ASC, product_id ASC;

NULL은 기본 오름차순에서 낮은 값으로 정렬됩니다. 마지막 예제는 note IS NULL이 거짓인 행을 먼저 배치하고, 메모·기본키로 다시 정렬해 NULL을 뒤로 보냅니다. 문자열 사이의 세부 순서는 정렬 규칙에 영향을 받으므로 NULL 위치와 동점 처리에 초점을 맞춰 확인합니다.

예상한 순서가 아닐 때 점검하기

LIMIT를 제거한 상태로 기본키와 모든 정렬 열을 출력해 전체 순서를 먼저 확인합니다. 별칭·정렬 방향·문자열 타입을 차례로 살피고, 동일값에서 고유한 보조 기준이 있는지 확인하세요. 서버의 기본키 인덱스 순서나 이전 실행 결과를 암묵적인 ORDER BY로 취급하지 않습니다.

정렬 기준을 사용자 입력으로 선택하게 하는 프로그램에서는 허용한 열과 방향만 매핑합니다. SQL 값 매개변수로 임의의 열 이름까지 안전하게 치환할 수 있다고 가정하지 않습니다. 페이지 크기도 정수 범위를 정하고, 음수·과도한 요청을 입력 단계에서 처리하는 편이 좋습니다.

다시 실습하려면 SELECT DATABASE();, SHOW CREATE TABLE products_17_lab;와 저장된 행을 확인합니다. 보관할 데이터가 없는 이 글의 연습 테이블이 확실할 때만 아래 문장으로 지운 뒤 준비 코드를 다시 실행합니다. DROP TABLE은 구조와 데이터를 함께 없애며 일반적인 ROLLBACK으로 취소되지 않습니다.

DROP TABLE shopcourse.products_17_lab;
같은 카테고리의 다른 글
MariaDB / 데이터베이스 저장 위치 변경하는 방법

MariaDB / 데이터베이스 저장 위치 변경하는 방법

MariaDB의 버전이 12.1이라고 할 때, 윈도우용 MariaDB의 기본 설치 위치는 C:\Program Files\MariaDB 12.1, 데이터베이스 저장 위치는 C:\Program Files\MariaDB 12.1\data입니다. 데이터베이스 저장 위치를 다음으로 변경해보겠습니다. D:\Database\MariaDB\data

MariaDB / 연산자 / 비교 연산자

MariaDB / 연산자 / 비교 연산자

MariaDB의 비교 연산자에 대하여 알아보겠습니다. 예제로 사용하는 테이블은 아래의 데이터를 가진 T_1이라는 테이블입니다. 각 열의 데이터 형식은 다음과 같습니다. C_1 : 정수 C_2 : 문자 C_3 : 날짜 +----+------+------+------------+ | ID | C_1 | C_2 | C_3 | +----+------+------+------------+ | 1 | 1 | ...

MariaDB 강좌 / MariaDB란? 데이터베이스·SQL·MySQL과의 관계

MariaDB 강좌 / MariaDB란? 데이터베이스·SQL·MySQL과의 관계

MariaDB 서버·클라이언트와 데이터베이스·테이블·행·열의 관계를 상품 예제로 이해합니다. SQL의 역할, MySQL과의 관계, 이후 강좌에서 사용할 실습 환경을 구분합니다.

MariaDB 강좌 / 윈도 함수로 누적 합계와 이전·다음 행 비교하기

MariaDB 강좌 / 윈도 함수로 누적 합계와 이전·다음 행 비교하기

누적 합계와 LAG·LEAD를 계산하고 동점 데이터로 ROWS·RANGE를 비교합니다. 날짜 필터를 누적 전후에 적용한 결과와 정렬·기간 경계를 확인합니다.

MariaDB 강좌 / Docker로 MariaDB 실습 환경 만들기

MariaDB 강좌 / Docker로 MariaDB 실습 환경 만들기

Compose 파일로 MariaDB 포트·암호 파일·데이터 볼륨·헬스체크를 구성합니다. 연결 확인과 컨테이너 교체 실습을 통해 데이터 유지, 초기화와 접속 오류의 차이를 이해합니다.

MariaDB 강좌 / Windows에 MariaDB 설치하고 서버 실행하기

MariaDB 강좌 / Windows에 MariaDB 설치하고 서버 실행하기

Windows MSI 설치에서 서버·클라이언트, 관리자 인증, 서비스와 포트를 설정합니다. SQL 실행을 확인하고 이후 강좌에서 사용할 학습용 계정을 준비하며 시작·접속 오류를 점검합니다.

MariaDB 강좌 / COUNT·SUM·AVG·MIN·MAX로 집계하기

MariaDB 강좌 / COUNT·SUM·AVG·MIN·MAX로 집계하기

COUNT·SUM·AVG·MIN·MAX의 집계 대상과 단위를 상품 재고로 비교합니다. NULL·0·빈 결과의 차이, 행별 계산 후 합계, 최솟값과 해당 행을 혼동하지 않는 기준을 설명합니다.

MariaDB 강좌 / 이벤트 스케줄러로 정기 작업 실행하고 결과 확인하기

MariaDB 강좌 / 이벤트 스케줄러로 정기 작업 실행하고 결과 확인하기

비활성 일회성 이벤트를 생성한 뒤 미래 시각으로 활성화하고 결과 행과 예약 메타정보를 대조합니다. 반복 작업의 중복·겹침 위험, 권한·시간대 점검과 안전한 중지·정리 방법도 설명합니다.

MariaDB 강좌 / 테이블 관계 설계하기: 일대다·다대다·외래키

MariaDB 강좌 / 테이블 관계 설계하기: 일대다·다대다·외래키

고객·상품·주문·상세 네 테이블로 일대다와 다대다 관계를 설계합니다. 복합키·주문 당시 단가·외래키 실패 입력과 삭제 제한을 실행하고 업무상 삭제 정책을 구분합니다.

MariaDB 강좌 / 두 연결로 격리 수준·잠금·교착 상태 확인하기

MariaDB 강좌 / 두 연결로 격리 수준·잠금·교착 상태 확인하기

별도 연결 A·B의 실행 순서대로 격리 수준, 행 잠금 대기와 교착 상태를 비교합니다. 초기화·재조회·오류 후 정리와 연결별 설정 복원까지 전체 코드로 확인합니다.