데이터 분석의 가장 기초가 되는 조회와 조건 필터링 기능을 실습함.
데이터 전체를 보거나, 정렬(ORDER BY)하고, 개수를 제한(LIMIT)하는 방법임.
-- 모든 데이터 조회
select * from fms.chick_info;
-- 전체 행 개수 조회
select count(*) from fms.chick_info;
-- 정렬 (계란 무게 내림차순 -> 부화일 오름차순 -> 번호 오름차순)
select chick_no, hatchday, egg_weight
from fms.chick_info
order by egg_weight desc, hatchday asc, chick_no asc;
-- Paging (상위 1개 건너뛰고 4개만 조회)
select chick_no, hatchday, egg_weight
from fms.chick_info
order by egg_weight desc, hatchday asc, chick_no asc
limit 4 offset 1;
-- 중복 제거 (부화일 종류 확인)
select distinct(hatchday) from fms.chick_info;
다양한 연산자를 활용하여 분석 대상 데이터를 추출함.
-- 성별이 'M'인 데이터 조회
select * from fms.chick_info where gender = 'M';
-- 수치 비교: 계란 무게가 70 이상인 데이터
select * from fms.chick_info where egg_weight >= 70;
-- 날짜 범위 조회 (BETWEEN A AND B)
select * from fms.chick_info where hatchday between '2025-01-01' and '2025-01-02';
-- OR 연산자 (무게가 69 초과이거나 62 이하)
select * from fms.chick_info where egg_weight > 69 or egg_weight <= 62;
-- 특정 품종 조회 (OR 대신 사용)
select * from fms.chick_info where breeds = 'C1' or breeds = 'C2';
-- 패턴 매칭 (LIKE): 품종이 'D'로 시작하는 데이터
select * from fms.chick_info where breeds like 'D%';
-- 리스트 포함 여부 (IN): 목적지가 부산 또는 울산
select * from fms.ship_result where destination in ('부산','울산');
-- NULL이 아닌 값 조회 (IS NOT NULL)
select * from fms.health_cond where note is not null;
ID 추출, 텍스트 가공 등을 위해 문자열 함수를 활용함.
-- 문자열 자르기 (LEFT, SUBSTRING, RIGHT)
select chick_no,
left(chick_no, 1),
substring(chick_no, 2, 3),
right(chick_no, 4)
from fms.chick_info limit 5;
-- 응용: ID에서 의미 추출하기 (CONCAT, SUBSTRING, CASE)
SELECT
chick_no,
LEFT(chick_no, 1) AS 출신농장,
CONCAT('20', SUBSTRING(chick_no, 2, 2)) AS 출생년도,
CASE WHEN SUBSTRING(chick_no, 4, 1) = '1' THEN 'M' ELSE 'F' END AS 성별,
RIGHT(chick_no, 4) AS 일련번호
FROM fms.chick_info
LIMIT 5;
-- 문자열 길이 확인
select length(chick_no) from fms.chick_info limit 5;
-- 문자열 합치기 (|| 연산자 활용)
select farm||gender||breeds as fgb from fms.chick_info limit 5;
-- 소문자 변환
select lower(gender) from fms.chick_info limit 5;
-- 문자열 치환
select replace(gender, 'M', 'Male') from fms.chick_info limit 5;
| 함수 | 설명 | 예시 |
|---|---|---|
| LEFT(str, n) | 왼쪽부터 n글자 추출 | LEFT('ABC', 1) 'A' |
| RIGHT(str, n) | 오른쪽부터 n글자 추출 | RIGHT('ABC', 1) 'C' |
| SUBSTRING(str, s, n) | s번째부터 n글자 추출 | SUBSTRING('ABC', 2, 1) 'B' |
| CONCAT(str1, ...) | 문자열 연결 ( | |
| LENGTH(str) | 문자열 길이 반환 | LENGTH('ABC') 3 |
| LOWER(str) | 소문자로 변환 | LOWER('Abc') 'abc' |
| REPLACE(str, old, new) | 문자열 치환 | REPLACE('A-B', '-', '') 'AB' |
GROUP BY를 통해 그룹별 통계를 구하고 HAVING으로 집계 결과에 조건을 적용함.
-- 일자별 생닭 무게 합계 (SUM)
select prod_date, sum(raw_weight) as prod
from fms.prod_result
group by prod_date;
-- 고객사별 출하 건수 (COUNT)
select customer, count(chick_no) as cnt
from fms.ship_result
group by customer;
-- 출하 건수가 10건 이상인 고객사 필터링 (HAVING)
select customer, count(chick_no) as cnt
from fms.ship_result
group by customer having count(chick_no) >= 10;
-- 복합 조건: 2/5 이후 데이터 중, 건수가 8건 이상인 것 정렬
select customer, count(*) as cnt
from fms.ship_result
where due_date >= '2025-02-05'
group by customer having count(*) >= 8
order by cnt desc;
COUNT(*)은 NULL 포함 전체 행.날짜 포맷 변경, NULL 처리, 조건부 값 생성을 다룸.
-- 날짜 형식 변환 (TO_CHAR)
select hatchday, to_char(hatchday, 'Mon') from fms.chick_info limit 5;
-- NULL 처리 (COALESCE): 습도가 NULL이면 60으로 대체
select farm, date, humid, coalesce(humid, 60)
from fms.env_cond
where date between '2025-01-23' and '2025-01-27' and farm = 'A';
-- 특정 값 NULL 처리 (NULLIF): 습도가 60이면 NULL로 처리
select farm, date, humid, nullif(humid, 60)
from fms.env_cond
where date between '2025-01-23' and '2025-01-27' and farm = 'A';
-- 조건부 등급 부여 (CASE WHEN)
select chick_no, egg_weight,
case
when egg_weight > 69 then 'H'
when egg_weight > 65 then 'M'
else 'L'
end "w_grade"
from fms.chick_info limit 10;
| 함수 | 설명 |
|---|---|
| TO_CHAR(값, 포맷) | 날짜/숫자를 문자열로 포맷팅 (YYYY-MM, Mon 등) |
| COALESCE(val1, val2) | 첫 번째로 NULL이 아닌 값을 반환 (NULL 대체용) |
| NULLIF(val1, val2) | 두 값이 같으면 NULL 반환 (0 나누기 방지 등) |
| CASE WHEN ... END | SQL의 IF-ELSE 조건문 |
| NOW() | 현재 시간 반환 |
관계형 데이터베이스의 핵심인 테이블 연결을 실습함.
-- JOIN: 생산 실적(a)과 출하 실적(b)을 chick_no 기준으로 병합
select a.chick_no, a.pass_fail, a.raw_weight,
b.order_no, b.customer
from fms.prod_result a
inner join fms.ship_result b
on a.chick_no = b.chick_no;
-- [도전] 성별에 따른 평균 계란 무게 (JOIN + GROUP BY)
select gender, avg(ch.egg_weight)
from fms.prod_result pr
inner join fms.chick_info ch
on pr.chick_no = ch.chick_no
group by ch.gender;
-- UNION: 쿼리 결과(행) 합치기
(select chick_no, gender, hatchday
from fms.chick_info
where farm = 'A' and gender = 'F' and hatchday = '2025-01-03')
union
(select 'A2300021', 'F', '2025-01-05');
실습 과정에서 주어진 미션의 정답 쿼리임.
-- 미션 1: 계란 무게 기준 상위 5마리 조회
select * from fms.chick_info order by egg_weight desc limit 5;
-- 미션 2: 체중 800 초과 & 체온 41 미만인 건강 상태
select * from fms.health_cond where weight > 800 and body_temp < 41;
-- 미션 3: 부화일별 마릿수가 10마리 초과인 날짜
select hatchday, count(*)
from fms.chick_info
group by hatchday having count(*) > 10
order by hatchday asc;
-- 미션 4: 조도가 10 이상인 날이 농장별로 며칠인지 조회
select farm, count(*) as high_lux_days
from fms.env_cond
where lux >= 10
group by farm;
-- 미션 5: 비고(Note)가 NULL이면 '없음'으로 표시
select chick_no, COALESCE(note, '없음') from fms.health_cond;
-- 미션 6: 평균 무게보다 무거운 계란을 낳은 닭 (서브쿼리)
SELECT * FROM fms.chick_info
WHERE egg_weight > (SELECT AVG(egg_weight) FROM fms.chick_info);
-- 미션 7: 합격/불합격 한글 표시 (CASE WHEN)
select chick_no, prod_date,
case when pass_fail = 'P' then '합격'
when pass_fail = 'F' then '불합격'
end result_status
from fms.prod_result;
-- 미션 8: 고객사별 주문 건수에 따른 등급 부여
select customer, count(*) as order_cnt,
case when count(*) >= 10 then 'A등급'
when count(*) < 5 then 'C등급'
else 'B등급'
end grade
from fms.ship_result group by customer;