첫 쿼리
쿼리는 데이터베이스에 던지는 질문입니다. 어떤 행에서 어떤 컬럼이 필요한가? 가장 단순한 조회는 모든 컬럼을 뜻하는 SELECT *와 테이블을 지정하는 FROM으로 작성합니다.
1
-- Every column of every product. Run it with F9 or Ctrl/Cmd + Enter.
SELECT *
FROM products
LIMIT 20;
결과 — 20행 중 처음 5행
| id | category_id | name | description | sku | price | cost | stock_quantity | weight_kg | attributes | is_active | created_at | updated_at |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 16 | Glass Orchard (Paperback ed.) | Glass Orchard (Paperback ed.) — built to last. | SKU-00001 | 913.72 | 443.95 | 179 | 6.18 | {"color":"green","warranty_months":12,"material":"fabric"} | 1 | 2024-01-13 07:13:52 | 2024-01-13 07:13:52 |
| 2 | 17 | Luma The Gene | Luma The Gene — built to last. | SKU-00002 | 332.64 | 161.72 | 83 | 5.893 | {"color":"silver","warranty_months":24,"material":"steel"} | 1 | 2022-06-16 08:45:20 | 2022-06-16 08:45:20 |
| 3 | 21 | Quill Helmet | Quill Helmet — designed for daily use. | SKU-00003 | 196.26 | 118.25 | 399 | 8.261 | {"color":"silver","warranty_months":24} | 1 | 2022-08-26 20:06:03 | 2022-08-26 20:06:03 |
| 4 | 16 | Kite Glass Orchard 3 | Kite Glass Orchard 3 — built to last. | SKU-00004 | 1719.68 | 845.91 | 243 | 5.263 | {"color":"silver","warranty_months":24} | 0 | 2022-07-19 11:34:27 | 2022-07-19 11:34:27 |
| 5 | 17 | The Gene (3rd ed.) | The Gene (3rd ed.) — a dependable everyday choice. | SKU-00005 | 122.8 | 69.5 | 357 | 1.898 | {"color":"red","warranty_months":36,"material":"aluminium"} | 1 | 2022-05-21 10:53:40 | 2022-05-21 10:53:40 |
브라우저의 새 탭에서 Planche가 열리고, 샘플 데이터베이스가 로드된 채로 이 쿼리가 들어갑니다. 이 페이지의 다른 예제도 같은 탭을 다시 씁니다. F9를 누르기 전까지는 아무것도 실행되지 않습니다.
*는 모든 컬럼을, LIMIT 20은 최대 20행을 뜻합니다. products처럼 행이 많은 테이블은 구조만 확인할 때 전부 읽어 올 이유가 없습니다. 전송할 데이터와 화면에 그릴 양이 함께 늘어나기 때문입니다.
Planche에도 결과 행 제한이 있습니다(설정 › 안전장치 › 행 제한). 그래도 쿼리에 LIMIT을 적어 두는 편이 좋습니다. 앱의 제한은 브라우저를 위한 것이고, 서버가 읽는 데이터 양까지 줄여 주지는 않습니다.
필요한 컬럼만 고르기
SELECT *는 테이블을 살펴볼 때 편리합니다. 필요한 정보가 정해졌다면 컬럼 이름을 직접 나열하세요. 결과를 읽기 쉬워지고 전송해야 할 데이터도 줄어듭니다.
2
SELECT name, sku, price, stock_quantity
FROM products
LIMIT 20;
결과 — 20행 중 처음 5행
| name | sku | price | stock_quantity |
|---|---|---|---|
| Glass Orchard (Paperback ed.) | SKU-00001 | 913.72 | 179 |
| Luma The Gene | SKU-00002 | 332.64 | 83 |
| Quill Helmet | SKU-00003 | 196.26 | 399 |
| Kite Glass Orchard 3 | SKU-00004 | 1719.68 | 243 |
| The Gene (3rd ed.) | SKU-00005 | 122.8 | 357 |
SELECT에 나열한 순서가 결과 컬럼의 순서가 됩니다. 테이블에 정의된 컬럼 순서와는 관계없습니다. 결과 컬럼 이름을 바꿀 때는 AS를 사용합니다.
WHERE로 행 거르기
SELECT가 컬럼을 고른다면 WHERE는 행을 고릅니다. 조건이 참인 행만 결과에 남깁니다.
3
SELECT name, price, stock_quantity
FROM products
WHERE price > 100
LIMIT 20;
결과 — 20행 중 처음 5행
| name | price | stock_quantity |
|---|---|---|
| Lean Startup (Deluxe ed.) | 107.37 | 84 |
| Pixel Sofa | 108.18 | 7 |
| Terra Pillow Pro | 113.67 | 0 |
| Pulse LED Strip | 114.86 | 480 |
| Brief Answers (3rd ed.) | 117.96 | 194 |
비교에는 =, <>(또는 !=), <, <=, >, >=를 사용합니다. 다만 NULL 비교에는 별도 규칙이 있습니다.
- 같음은
=하나입니다.==가 아닙니다. - NULL은 무엇과도 같지 않습니다. NULL끼리도 같지 않습니다. 무게가 기록되지 않은 상품이 아무리 많아도
WHERE weight_kg = NULL은 한 행도 찾지 못합니다.IS NULL과IS NOT NULL을 써야 합니다. 다음 레슨에서 제대로 다룹니다.
ORDER BY로 정렬하기
ORDER BY가 없으면 결과 순서는 보장되지 않습니다. 지금 보이는 순서가 데이터나 인덱스 변화 뒤에도 유지된다고 기대하면 안 됩니다.
4
SELECT name, price
FROM products
ORDER BY price DESC
LIMIT 20;
결과 — 20행 중 처음 5행
| name | price |
|---|---|
| Glide GPS Watch Pro | 2484.4 |
| Terra 3D Puzzle | 2481.77 |
| Aria Castle Kit | 2479.41 |
| Aria LED Strip Pro | 2463.41 |
| Nova Brief Answers | 2445.49 |
DESC는 큰 값부터, ASC(기본값)는 작은 값부터 정렬합니다. ORDER BY price DESC와 LIMIT 20을 함께 쓰면 비싼 상품 20개를 가져옵니다. 먼저 전체를 가격순으로 정렬하고, 그 결과에서 20행을 고르는 순서입니다.
Planche에서는 결과 그리드의 컬럼 헤더를 눌러 정렬할 수도 있습니다. 오름차순, 내림차순, 정렬 해제 순으로 바뀌며 서버에서 다시 조회합니다. 이때 만들어지는 SQL을 보면 직접 작성한 쿼리도 확인할 수 있습니다.
정렬 키를 여러 개 쓰기
정렬 기준을 여러 개 지정하면, 앞 기준의 값이 같은 행을 뒤 기준으로 다시 정렬합니다.
5
SELECT category_id, name, price
FROM products
ORDER BY category_id, price DESC
LIMIT 30;
결과 — 30행 중 처음 5행
| category_id | name | price |
|---|---|---|
| 2 | Aria Notebook | 2116.4 |
| 2 | Ember Laptop Plus | 2087.98 |
| 2 | Sol Notebook | 1982.34 |
| 2 | Sol Ultrabook | 1942.47 |
| 2 | Nimbus Ultrabook | 1933.06 |
이 쿼리는 카테고리 순으로 정렬한 뒤, 같은 카테고리 안에서는 가격이 높은 상품부터 보여 줍니다.
표현식과 별칭
SELECT에는 컬럼뿐 아니라 산술식이나 함수 호출도 넣을 수 있습니다. 행마다 계산된 값 하나가 만들어지고, AS로 그 결과에 이름을 붙일 수 있습니다.
6
SELECT name,
price,
cost,
ROUND(price - cost, 2) AS margin
FROM products
WHERE is_active = 1
ORDER BY margin DESC
LIMIT 15;
결과 — 15행 중 처음 5행
| name | price | cost | margin |
|---|---|---|---|
| Ember Tab Plus | 2412.93 | 984.94 | 1427.99 |
| Aria LED Strip Pro | 2463.41 | 1098.69 | 1364.72 |
| Luma Denim Jacket Pro | 2357.59 | 993.24 | 1364.35 |
| Drift A Winter Letter | 2422.5 | 1082.43 | 1340.07 |
| Nova Brief Answers | 2445.49 | 1108.09 | 1337.4 |
ROUND(price - cost, 2) AS margin은 테이블에 없는 값을 계산하고 결과 컬럼 이름을 margin으로 지정합니다. 이 별칭은 ORDER BY에서는 사용할 수 있지만 WHERE에서는 사용할 수 없습니다. 두 절이 평가되는 시점이 다르기 때문입니다.
FROM -> WHERE -> SELECT -> ORDER BY -> LIMIT
ORDER BY가 실행될 때는 SELECT가 이미 margin을 만들어둔 뒤입니다. 반면 WHERE가 실행될 때는 아직 없습니다. 그래서 WHERE margin > 50은 오류입니다. 표현식을 그대로 한 번 더 쓰거나, 이 쿼리를 다른 쿼리로 감싸야 합니다. 이 순서를 기억해두세요. WHERE가 그룹핑 전에 행을 거르고 HAVING이 그룹핑 후에 거르는 이유도 같은 순서로 설명됩니다. 두 레슨 뒤에 나옵니다.
여기까지로 할 수 있는 것
이 네 절만으로도 가장 비싼 상품 20개, 재고가 떨어진 상품, 판매 중인 상품 가운데 마진이 큰 상품처럼 한 테이블 안의 질문에 답할 수 있습니다. 고객과 주문처럼 두 테이블을 함께 읽는 질문에는 조인이 필요합니다.
예제의 숫자나 컬럼 이름을 바꿔 실행해 보세요. 결과가 어떻게 달라지는지 보면 각 절의 역할이 더 분명해집니다.