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 강좌 / UPDATE·DELETE를 실행하기 전 대상 행 확인하기

MariaDB 강좌 / UPDATE·DELETE를 실행하기 전 대상 행 확인하기

UPDATE·DELETE 전에 기본키와 현재값으로 대상 행을 확인하고, InnoDB 트랜잭션에서 수정·삭제 결과를 검증한 뒤 취소합니다. 영향받은 행 수와 ROLLBACK의 적용 한계도 설명합니다.

MariaDB / 데이터베이스 / 조회, 생성, 삭제, 이름 변경

MariaDB / 데이터베이스 / 조회, 생성, 삭제, 이름 변경

MariaDB에서 데이터베이스를 조회하는 방법, 생성하는 방법, 삭제하는 방법, 이름을 변경하는 방법에 대해서 알아봅니다.

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

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

Ubuntu APT 설치 후 서버 실행·자동 시작·관리자 소켓 인증을 확인합니다. 로컬 TCP 학습 계정을 만들고 패키지 버전, 인증 오류와 서비스 로그를 확인하는 절차를 설명합니다.

MariaDB 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

MariaDB 강좌 / 첫 실습: 상품 테이블을 만들고 데이터를 넣어 조회하기

상품 세 건을 저장하는 전체 SQL로 테이블 생성·입력·조회 과정을 실습합니다. 구조와 행 수, 가격·재고 조건의 예상 결과를 확인하고 반복 입력 오류와 실습 테이블 초기화 범위를 구분합니다.

MariaDB 강좌 / VIEW로 자주 쓰는 조회를 정의하기

MariaDB 강좌 / VIEW로 자주 쓰는 조회를 정의하기

CREATE VIEW로 결제 주문 합계를 정의하고 원본 변경·취소가 조회 결과에 반영되는지 확인합니다. CTE와의 차이, INVOKER·DEFINER 권한, 집계 뷰의 수정 제한과 정리 순서를 설명합니다.

MariaDB 강좌 / 조회 종합 실습: 월별 매출·고객별 구매·미판매 상품

MariaDB 강좌 / 조회 종합 실습: 월별 매출·고객별 구매·미판매 상품

월별 paid 매출, 미구매 포함 고객별 구매 금액, 미판매 상품 조회를 종합 실습합니다. 주문·상세 단위와 취소 정책을 정하고 세 결과의 전체 금액을 교차 검증합니다.

MariaDB / 연산자 / 논리 연산자

MariaDB / 연산자 / 논리 연산자

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

MariaDB 강좌 / 사용자 계정 만들고 필요한 권한만 부여하기

MariaDB 강좌 / 사용자 계정 만들고 필요한 권한만 부여하기

사용자·호스트 조합을 확인하고 상품 한 테이블의 SELECT만 허용하는 계정을 만듭니다. 새 연결의 허용·거절 시험, 권한 회수와 기존 계정을 덮어쓰지 않는 정리 절차를 설명합니다.

MariaDB 강좌 / 서버 설정·SQL 모드·시간대·로그 확인하기

MariaDB 강좌 / 서버 설정·SQL 모드·시간대·로그 확인하기

설정 파일·GLOBAL·SESSION의 차이를 기준으로 MariaDB 동작을 확인합니다. SQL 모드 오류와 TIMESTAMP·DATETIME 시간대 실습, 로그 조건 점검 및 변경 복구 절차를 제공합니다.

MariaDB 강좌 / 조회 조건·정렬·페이지 나누기를 개선하기

MariaDB 강좌 / 조회 조건·정렬·페이지 나누기를 개선하기

날짜 범위·정렬·키셋 페이지 조회를 같은 주문 데이터로 검증합니다. 함수 조건의 버전별 최적화, 동점 비교 방향, 포함 검색의 의미와 실제 계획·측정 기준을 설명합니다.