
CREATE DATABASECREATE TABLEALTER TABLEpg_dumppg_restorePoint-in-Time Recovery(PITR)CREATE USER CREATE ROLE REVOKEpg_hba.conf실무에서 일반적인 규칙
_', 식별자와 객체 이름은 "각 테이블의 사용목적, 이름, 작성자, 비고사항 등의 테이블에 대한 기록뿐만 아니라 테이블에 포함된 각 컬럼의 이름, 데이터 타입 및 제약조건을 기록한 문서양식
CREATE TABLE 테이블이름(
id SERIAL PRIMARY KEY,
머시기 INT,
저시기 INT,
머시기 VARCHAR,
FOREIGN KEY 칼럼이름 REFERENCES 테이블이름 칼럼이름
);
INSERT INTO 테이블 (필드이름1, 필드이름2, ...)
VALUES (값1, 값2, ...);
ALTER TABLE 테이블이름
ADD COLUMN 컬럼이름 데이터타입;
DROP TABLE 테이블이름;
-- 스키마 설정하여 이름 생략하기
SET search_path TO practice;
특정 테이블에서 특정 열만 선택해 데이터를 조회
SELECT 열이름 FROM 테이블명;
-- 전체 데이터 조회
SELECT * FROM practice.product_info;
-- 전체 데이터 개수 출력
SELECT count(*) FROM practice.product_info;
-- 원하는 열만 조회
SELECT serial_no, prod_start_date, target_weight FROM practice.product_info;
-- 열 이름 바꿔 조회
SELECT serial_no AS sn, prod_start_date "생산일자" FROM practice.product_info;
-- 지금 date에서 1일 빼기
SELECT now() - INTERVAL '1 day';
-- 정렬하여 조회(target_weight → prod_start_date 순 기준으로 정렬)
SELECT serial_no, prod_start_date, target_weight from product_info ORDER BY target_weight DESC, prod_start_date;
DESC or ASC-- 특정 개수만 조회(offset만큼 건너뜀)
SELECT * FROM product_info LIMIT 6 OFFSET 2;
LIMIT은 앞선 연산들이 모두 끝난 후 실행된다.-- 유니크 조회
SELECT DISTINCT(컬럼이름) FROM 테이블;
SELECT 컬럼이름 FROM 테이블명 WHERE 조건;



SELECT * FROM product_info WHERE factory_code = 'A';
SELECT * FROM product_info WHERE target_weight >= 70;
SELECT * FROM product_info WHERE prod_start_date BETWEEN '2026-01-01' AND '2026-01-02';
SELECT * FROM product_info WHERE target_weight > 69 OR target_weight <= 62;
SELECT * FROM product_info WHERE model_id LIKE 'M%';
SELECT * FROM delivery_log WHERE destination IN ('Busan', 'Ulsan');
SELECT * FROM factory_env WHERE humid IS NULL;
SELECT * FROM sensor_log WHERE remarks IS NOT NULL;
SELECT * FROM product_info WHERE model_id BETWEEN 'M1' AND 'M2';
SELECT * FROM product_info WHERE model_id = 'M1' OR model_id = 'M2';
SELECT * FROM product_info WHERE model_id IN ('M1', 'M2');


SELECT serial_no, left(serial_no, 1), substring(serial_no, 2, 3), right(serial_no, 4) FROM product_info LIMIT 5;

-- 글자수
SELECT length(serial_no) FROM product_info LIMIT 5;
-- 3개의 칼럼 데이터를 하나의 칼럼으로 합쳐 보여주기
SELECT REPLACE(REPLACE(factory_code, 'A', '평택공장'), 'B', '기흥공장')||line_id||model_id AS flm FROM product_info LIMIT 5;
-- 소문자 변환
SELECT lower(factory_code) FROM product_info LIMIT 5;


SELECT
sum(target_weight) total_weight,
avg(target_weight) avg_weight,
max(target_weight) max_weight,
min(target_weight) min_weight,
count(*) AS total_count
FROM product_info;
-- →데이터 양이 늘어날수록 속도적 문제
SELECT 집계함수(열이름) FROM 테이블명 GROUP BY 범주열이름;SELECT qa_date, sum(net_weight) AS qa
FROM qa_result
GROUP BY qa_date
LIMIT 5;

SELECT client_name, count(serial_no) AS cnt
FROM delivery_log
GROUP BY client_name;

SELECT client_name, count(serial_no) AS cnt
FROM delivery_log
GROUP BY client_name
HAVING count(serial_no) >= 15;
--shipped date가 2026-02-05 이후인 데이터에 대해서 출하건수가 8개 이상인 고객사만 필터링
SELECT client_name, count(serial_no) AS "출하건수"
FROM delivery_log
WHERE shipped_date >= '2026-02-05'
GROUP BY client_name
HAVING count(*) >= 8;


SELECT prod_start_date , TO_CHAR(prod_start_date, 'Mon')
FROM product_info
LIMIT 5;

COALESCE
-- NULL값을 60으로 대체
SELECT line_id, check_date , humid, coalesce(humid, 60)
FROM factory_env
WHERE check_date BETWEEN '2026-02-01' AND '2026-02-27'
AND line_id = 'A';

NULLIF
-- 해당하는 값을 NULL로 대체
SELECT line_id, check_date , humid, NULLIF(humid, 42)
FROM factory_env
WHERE check_date BETWEEN '2026-02-01' AND '2026-02-27'
AND line_id = 'A';

SELECT
serial_no,
target_weight,
CASE
WHEN target_weight > 600 THEN 'H'
WHEN target_weight > 500 THEN 'M'
ELSE 'L'
END "w_grade"
FROM product_info;

SELECT *
FROM product_info
ORDER BY target_weight desc
LIMIT 5;

SELECT *
FROM sensor_log
WHERE current_weight > 500 AND cpu_temp < 60;

SELECT prod_start_date, count(serial_no) AS "count"
FROM product_info
GROUP BY prod_start_date
HAVING count(*) > 5;

SELECT line_id, count(DISTINCT check_date) AS "high_voltage_days"
FROM factory_env
WHERE voltage > 220
GROUP BY line_id;

SELECT serial_no, COALESCE (remarks , '없음')
FROM sensor_log;
SELECT serial_no,
CASE
WHEN remarks IS NULL OR remarks = '' THEN '없음'
ELSE remarks
END
FROM sensor_log;

SELECT AVG(target_weight)
FROM product_info;
SELECT *
FROM product_info
WHERE target_weight > 574;
-- 저도 서브쿼리 날려야 하는거 아는데 강사님이 이렇게 하라네요...

SELECT serial_no, qa_date,
REPLACE(REPLACE(qa_status, 'P', '합격'), 'F', '불합격') AS "qa_status"
FROM qa_result;

SELECT client_name, count(*) AS "order_cnt",
CASE
WHEN count(*) >= 17 THEN 'A등급'
WHEN count(*) >= 15 THEN 'B등급'
ELSE 'C등급'
END AS "grade"
FROM delivery_log
GROUP BY client_name;
테이블이 두 개 이상인 경우 테이블을 합치거나 정보를 조합해야 할 때 사용



SELECT Employee.Name, Employee.Age, Contact_Info.Address
FROM Employee
INNER JOIN Conatact_Info
ON Employee.ID = Contact_Info.ID;
SELECT *
FROM qa_result qr INNER JOIN delivery_log dl
ON qr.serial_no = dl.serial_no;
SELECT *
FROM qa_result qr, delivery_log dl
where qr.serial_no = dl.serial_no;
-- qa_result, product_info 생산 결과와 정보 조인하여 line_id별 평균 중량 구하기
SELECT line_id, avg(qr.net_weight)
FROM qa_result qr, product_info t
WHERE qr.serial_no = t.serial_no
GROUP BY t.line_id;
-- qa_result에서 defect가 있던 제품 리스트
SELECT t.serial_no, t.line_id, qr.qa_date
FROM qa_result qr, product_info t
WHERE qr.serial_no = t.serial_no
AND qr.defect_yn = 'Y';


SELECT *
FROM qa_result qr LEFT OUTER JOIN delivery_log dl
ON qr.serial_no = dl.serial_no;
열(Column)구조가 같은 두 쿼리 결과를 행(row) 단위로 붙임

UNION 또는 UNION ALL(중복) 절을 이용(SELECT serial_no, model_id, prod_start_date
FROM product_info
WHERE line_id = 'A'
AND model_id = 'M2'
AND prod_start_date = '2026-01-22')
UNION
(SELECT '롸롸롸', '뫄뫄뫄', '2026-01-23');
