| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |
- 데이터베이스
- ai 에이전트
- PHP객체지향
- OOP
- LLM
- MySQL
- 데코레이터패턴
- 소프트웨어설계
- SQL기초
- Agent Loop
- 디자인패턴
- Laravel
- 라라벨
- mcp server
- 어댑터패턴
- ai agent
- docker network
- 매직메서드
- docker
- Tool Calling
- PHP
- dhgrp
- mcp client
- 객체복제
- MCP
- 객체지향
- SQL
- linux 권한
- SQL문법
- 인덱스
- Today
- Total
개발블로그
[SQL] SQL 기본 조회 본문
SQL 작성 순서와 실행 순서
SQL 작성 순서
SELECT 조회할_값
FROM 테이블
JOIN 다른_테이블 ON 연결_조건
WHERE 행_조건
GROUP BY 그룹화할_컬럼
HAVING 그룹_조건
ORDER BY 정렬_기준
LIMIT 조회할_개수
OFFSET 건너뛸_개수;
| 구문 | 역할 |
| SELECT | 결과에 포함할 컬럼이나 값 지정 |
| FROM | 데이터를 가져올 테이블 지정 |
| JOIN, ON | 다른 테이블과 연결 |
| WHERE | 조건에 맞는 행만 선택 |
| GROUP BY | 같은 값을 가진 행을 그룹화 |
| HAVING | 그룹화된 결과에 조건 적용 |
| ORDER BY | 결과 정렬 |
| LIMIT | 조회할 행의 개수 제한 |
| OFFSET | 앞에서부터 일정 개수 건너뛰기 |
SQL의 논리적 실행 순서
- FROM
- JOIN / ON
- WHERE
- GROUP BY
- HAVING
- SELECT
- DISTINCT
- ORDER BY
- LIMIT / OFFSET
순서를 명시해야 하는 이유
: SQL의 각 구문은 서로 다른 시점에서 처리된다. 따라서 특정 구문에서는 그 시점보다 앞서 처리된 데이터와 결과는 참조할 수 있다.
- WHERE에서는 SELECT 별칭을 사용할 수 없는 경우가 많다
=> WHERE이 실행된느 시점에서느 아직 별칭이 만들어지지 않았기 때문 - 집계 결과는 WHERE가 아니라 HAVING에서 조건을 적용
=> WHERE가 실행되는 시점에는 아직 GROUP BY 가 처리되지 않았기 때문 - ORDER BY에서는 SELECT 별칭을 사용할 수 있음
SELECT와 FROM
SELECT 컬럼명 -- 조회 결과에 포함할 컬럼이나 값을 지정
FROM 테이블명; -- 데이터를 가져올 테이블을 지정
-- 여러 컬럼 조회 : 컬럼명을 쉼표로 구분
SELECT name, email
FROM users;
-- 모든 컬럼 조회 : 별포
SELECT *
FROM users;
별칭과 DISTINCT
별칭(Alias)
조회 결과에서 컬럼이나 테이블에 임시 이름을 붙이는 기능.
SELECT 컬럼명 AS 별칭
FROM 테이블명;
DISTINCT
조회 결과에 중복된 행을 제거.
SELECT DISTINCT 컬럼명
FROM 테이블명;
WHERE와 조건 연산자
WHERE
테이블의 전체 행 중에서 조건을 만족시키는 행만 조회할 때 사용하는 구문
SELECT 컬럼명
FROM 테이블명
WHERE 조건;
조건에 사용하는 연산자
비교 연산자
| 연산자 | 의미 | 예시 |
| = | 같다 | status = 'active' |
| !=, <> | 같지 않다 | status != 'inactive' |
| > | 크다 | price > 10000 |
| >= | 크거나 같다 | price >= 10000 |
| < | 작다 | stock < 10 |
| <= | 작거나 같다 | stock <= 10 |
논리 연산자
| 연산자 | 의미 |
| AND | 모든 조건을 만족 |
| OR | 하나 이상의 조건을 만족 |
| NOT | 조건의 반대 |
조건 구문
| 구문 | 용도 |
| IN | 여러 값 중 하나와 일치하는지 확인 |
| BETWEEN | 지정한 범위에 포함되는지 확인 |
| LIKE | 문자열 패턴 검색 - 기호 % => 길이에 제한 없이 모든 문자열 _ => 문자 한 개 |
| IS NULL | 값이 NULL인지 확인 |
GROPU BY와 HAVING
개념
GROUP BY
→ 여러 행을 기준별로 그룹화
(그룹 하나당 결과 한 행)
HAVING
→ 그룹화된 결과 중 조건을 만족하는 그룹만 선택
여러 개의 행
↓ GROUP BY
같은 값을 가진 행끼리 그룹화
↓ 집계 함수
그룹별 개수·합계·평균 등의 결과 생성
↓ HAVING
조건을 만족하는 그룹만 선택
SELECT
그룹_기준,
집계함수(대상_컬럼) AS 집계_결과 -- 그룹별 개수·합계·평균 등을 계산
FROM 테이블명
WHERE 개별_행_조건 -- 그룹화하기 전에 개발 행을 필터링
GROUP BY 그룹_기준 -- 같은 기준값을 가진 행끼리 그룹화
HAVING 집계_결과_조건; -- 계산된 그룹 결과를 필터링
주로 사용하는 집계함수
| 함수 | 역할 |
| COUNT() | 행의 개수 |
| SUM() | 값의 합계 |
| AVG() | 값의 평균 |
| MAX() | 최댓값 |
| MIN() | 최솟값 |
자주 사용하는 형태
상태 / 유형별 개수
관리자 통계, 대시보드, 상태별 현황
SELECT
status,
COUNT(*) AS count
FROM records
GROUP BY status;
대상별 합계
SELECT
DATE(created_at) AS date,
COUNT(*) AS count
FROM records
GROUP BY DATE(created_at);
날짜별 통계
SELECT
DATE(created_at) AS date,
COUNT(*) AS count
FROM records
GROUP BY DATE(created_at);
중복 데이터 찾기
SELECT
email,
COUNT(*) AS duplicate_count
FROM users
GROUP BY email
HAVING COUNT(*) >= 2;
일정 기준을 넘은 그룹 조회
SELECT
target_id,
COUNT(*) AS count
FROM records
GROUP BY target_id
HAVING COUNT(*) >= 10;
그룹별 최근 값 확인
사용자별 최근 활동이나 상품별 마지막 주문일 등을 확인
SELECT
target_id,
MAX(created_at) AS latest_at
FROM records
GROUP BY target_id;
ORDER BY
개념
조회 결과를 지정한 순서에 따라 정렬할 때 사용
문법
SELECT 컬럼명
FROM 테이블명
ORDER BY 정렬_기준 ASC | DESC;
-- ASC (기본값) : 오름차순, DESC (내림차순)
오름차순과 내림차순
숫자
ASC → 작은 값부터
DESC → 큰 값부터
문자열
ASC → 앞선 문자부터
DESC → 뒤의 문자부터
날짜와 시간
ASC → 오래된 데이터부터
DESC → 최근 데이터부터
NULL
ASC → 앞쪽에 나타남
DESC → 뒤쪽에 나타남
여러 기준으로 정렬
앞의 기준부터 차례대로 적용함
SELECT id, status, created_at
FROM records
ORDER BY status ASC, created_at DESC;
-- status를 오름차순으로 정렬
-- status가 같은 행끼리는 created_at을 내림차순으로 정렬
LIMIT과 OFFSET
개념
OFFSET → 앞에서 몇 행을 건너뛸지 정함
LIMIT → 그다음 몇 행을 가져올지 정함
문법
SELECT 컬럼
FROM 테이블
ORDER BY 정렬_기준 -- 함께 사용 (결과의 순서를 명확하게 정하기 위해)
LIMIT 조회할_개수
OFFSET 건너뛸_개수;
-- 동일
LIMIT 건너뛸_개수, 조회할_개수;
사용패턴
페이지네이션
| 구분 | OFFSET 방식 | 키셋 방식 |
| 다음 조회 기준 | 건너뛸 행의 개수 | 이전 결과의 마지막 정렬값 |
| 전달값 예시 | OFFSET 100 | WHERE id < 96 |
| 전달값 생성 | 페이지 번호로 계산 | 이전 결과에서 가져옴 |
| 페이지 번호 이동 | 쉬움 | 어려움 |
| 뒤쪽 데이터 조회 | 건너뛸 행이 많아질 수 있음 | 마지막 위치 이후부터 조회 |
| 주요 사용처 | 일반적인 페이지 번호 목록 | 무한 스크롤, 피드, 로그 |
OFFSET 방식
OFFSET = (현재페이지 - 1) * 페이지당 개수
-- 1페이지
LIMIT 10 OFFSET 0;
-- 2페이지
LIMIT 10 OFFSET 10;
-- 3페이지
LIMIT 10 OFFSET 20;
키셋 페이지네이션(Keyset Pagination)
페이지 번호와 OFFSET 대신, 마지막으로 조회한 행의 정렬값을 기준으로 다음 데이터를 가져 옴.
(커서 기반 페이지네이션)
ex]
-- OFFSET방식 --
SELECT 컬럼
FROM 테이블
ORDER BY 정렬_컬럼 DESC
LIMIT 조회_개수
OFFSET 건너뛸_개수;
-- 5개씩 조회한다고 할 때
SELECT id
FROM records
ORDER BY id DESC
LIMIT 5
OFFSET 5;
/**
1페이지 → OFFSET 0
2페이지 → OFFSET 5
3페이지 → OFFSET 10
*/
-- OFFSET = (현재페이지 - 1) * 페이지당 조회 개수
-- 키셋 방식--
-- => 이전 조회 결과의 마지막 정렬값을 기준으로 다음 범위를 조회
-- 첫 번째 조회
SELECT id
FROM records
ORDER BY id DESC
LIMIT 5;
-- 결과 : 100, 99, 98, 97, 96
-- 다음 조회
SELECT id
FROM records
WHERE id < 96 -- 마지막 정렬값을 조건으로 전달
ORDER BY id DESC
LIMIT 5;
-- 결과 : 95, 94, 93, 92, 91
가장 크거나 작은 값 조회
SELECT id, name, price
FROM products
ORDER BY price DESC, id DESC
LIMIT 1;
'STUDY > SQL' 카테고리의 다른 글
| [SQL] 서브쿼리 (0) | 2026.07.29 |
|---|---|
| [SQL] JOIN (0) | 2026.07.29 |
| [SQL] SQL 개념 (0) | 2026.07.29 |
| [데이터베이스와 DBMS 기초] 관계형 데이터베이스의 기본 구조 (0) | 2026.07.28 |
| [데이터베이스와 DBMS 기초] 데이터베이스와 DBMS (0) | 2026.07.27 |