키워드
RDBMS, SQL 기초, DDL, DML
SQL 학습 목적
- 데이터로 데이터 프로덕트(머신러닝 모델, 데이터 리포트)를 만들고자함
- 데이터 베이스에서 원하는 데이터를 가져올 때 SQL을 사용
- SQL을 이용하면..
- 원하는 형태로 데이터를 가져올 수 있다.
- 효율적으로 데이터를 가져올 수 있다.
- 간단한 데이터 분석을 수행할 수 있다.
- 기초 통계량 추출 등이 가능
RDBMS / SQL 개요
SQL 기초 구문
- SELECT
- FROM
- 어디에서 (어느 테이블에서)
- 여러개의 DB가 있는 경우 명시해줘야함
- WHERE
- 필터링 구문
- 해당 조건에 일치하는 경우만 조회함 (논리/비교 연산자 사용)
- 가져올 행을 선택
SELECT name, category
FROM products
- 모든 컬럼을 가져올 땐 SELECT 문에 * 사용
- 하지만 이는 테이블이 큰 경우 비효율적일 수 있음
- 데이터 스키마를 미리 확인하고 쿼리를 짜기
SELECT product_id, category
FROM products
WHERE 1=1
AND category = "주방용품"
- 1=1이라는 무조건 참인 조건을 추가하면 코드 수정이 용이해짐
- 조건들을 주석 처리로 조건을 수정할 수 있기 때문에
- 위 쿼리는 category 값이 “주방용품”인 데이터만 조회
SELECT product_id, name
FROM products
WHERE 1=1
AND price < 30000
LIMIT 2
- LIMIT은 조회 데이터 갯수를 제한함
- 해당 코드는 상위 2개 데이터를 조회
비교 연산자, 논리 연산자
AND category = "주방용품"
AND price = 2000
- 등호 연산자는 숫자, 문자에 모두 적용 가능하다
AND price > 5000
- price 값이 5000원보다 큰 데이터 조회
AND category <> "키즈"
AND category != "키즈"
- <>는 ‘같지 않음’ 연산자로 테이블에서 카테고리 값이 “키즈”가 아닌 데이터를 조회한다.
- 파이썬에서와 동일하기
!=도 같지 않음을 의미한다.
AND (category = "주방용품" OR name = "손목보호대")
- OR 연산자를 이용해 두 조건에 맞는 데이터를 모두 조회 가능하다.
- 위의 경우 IN을 사용할 수도 있음
AND NOT category = "키즈"
- NOT은 true와 false를 뒤집는 연산자이다.
- 이 쿼리에선 category가 키즈가 아닌 데이터만 필터링된다.
AND category IN ("스포츠","디지털","식품")
- IN은 좌측의 컬럼의 값이 우측 집합에 포함되어있는 데이터만 필터링 된다.
- 이 쿼리에선 category가 "스포츠","디지털","식품"에 해당하는 데이터만 필터링된다.
AND name LIKE "%보호%"
- %는 모든 문자열을 의미
- LIKE는 문자열에 특정 문자의 포함 여부를 확인하는 연산자이다.
- 위 쿼리는 name에 ‘보호’가 포함된 모든 데이터를 조회한다.
AND name LIKE "_그릇"
- _(언더바)는 한 글자를 의미한다.
- 즉 ‘밥그릇’ 같은 ‘그릇’ 앞 한 글자를 더 갖는 데이터만 조회되고 ‘고양이밥그릇’을 name으로 갖는 데이터는 조회되지 않는다.
AND price BETWEEN 5000 and 15000
AND purchase_date between '20231001' and '20231003'
- BETWEEN은 특정 범위에 포함되는 데이터만 조회하는 연산자
- 끝 두 값을 모두 포함함
- 날짜 데이터도 between으로 필터링할 수 있음
- 날짜 데이터는문자열인가 숫자인가 아님 날짜 타입이 따로 있나?
AND purchase_date IS NULL
AND product_name IS NOT NULL
- IS NULL로 특정 컬럼이 비어있는(NULL)인 데이터를 필터링할 수 있음
ISNULL(컬럼명) 이라는 함수도 사용 가능하다.
- IS NOT NULL은 is null과 반대로 특정 컬럼이 NULL이 아닌 데이터를 필터링할 수 있다.
정렬과 집계
ORDER BY price
ORDER BY price DESC
- 특정 열의 값을 기준으로 데이터를 오름차순, 내림차순으로 정렬한다.
- 디폴트는 오름차순(ASC)이다.
- DESC(내림차순)을 써주면 내림차순으로 정렬된다.
- 숫자뿐만 아니라 문자열에도 적용 가능 (한글-가나다 순, 영어-알파벳 순)
ORDER BY price DESC, name
ORDER BY 1 DESC, 2
- 두 개 이상의 열 값 기준으로 데이터 정렬이 가능하다.
- 위의 경우 price 기준으로 내림차순으로 1차 정렬 후, 2차로(price가 같은 경우) name에 대해 정렬한다.
- 아래와 같이 숫자 표현을 사용할 수 있다.
- 최종 결과의(SELECT의) 첫번째, 두번째 결과로 1,2를 이용할 수 있다.
- LIMIT과 조합해 상위 N개, 하위 N개를 뽑을 수 있다.
SUM(price) as sum_price, avg(price) as avg_price
- sum, avg와 같은 집계 함수를 이용해 특정 컬럼 값의 합, 평균을 구할 수 있다.
SELECT name as name_v2, 1 as new_col
SELECT name as name_v2, 'tmp' as new_col
- 1 as new_col과 같이 작성함으로써 모든 데이터가 해당 컬럼의 값으로 1을 갖는 새로운 컬럼을 만들 수 있다.
- 1 대신 문자열 등으로도 값을 채울 수 있음
count(1) as cnt
count(name)
count(distinct price) as unique_price_cnt
- count(1)은 테이블의 행 수를 의미
- 아래와 같이 count(컬럼)으로 작성하면 null 값을 갖는 데이터는 제외되고 count된다.
- 컬럼 앞에 distinct를 붙이면 고유한 값만을 count함
SELECT category, count(1) as sales_cnt
FROM products_v3
WHERE 1=1
AND sale_yn = 'yes'
GROUP BY 1
ORDER BY 2, 1 DESC
- category로 그룹화 후 각 그룹의 데이터 갯수를 count
GROUP BY 1, 2
- 2개 이상의 컬럼을 기준으로도 그룹화가 가능
- 각각의 조합으로 그룹화됨
GROUP BY 1,2
HAVING avg_price > 3000
- HAVING은 집계(그룹화) 이후 조건절로 보면 됨.
- 즉 그룹화 후 avg_price가 3000원이 넘는 데이터만 필터링할 수 있음
- HAVING avg_price > 3000은 where price>3000 과는 다름
기초 SQL 함수
SELECT CONCAT(category, '-', name) as comb_name
SELECT CONCAT(category, ' ', name) as comb_name
SELECT CONCAT(category, 5000, name) as comb_name
SELECT CONCAT(name, '의 가격은', price,'입니다.') as comb_name
- CONCAT은 여러 컬럼의 문자열을 합치고자 할 때 사용
- 각 데이터의 category, name 값을 - 으로 잇는다.
- 숫자 타입의 컬럼도, 이음값도 모두 문자열로 변환되어 concat된다.
SUBSTRING(name, 1, 2) as sub_string
LEFT(name, 3) as sub_string
RIGHT(name, 3) as sub_string
- SUBSTRING 특정 컬럼의 값을 시작, 길이를 입력 받아 추출하는 함수이다.
- 위 쿼리에선 name 컬럼의 값을 1번째 문자부터 길이 2만큼 추출한다.
- LEFT는 왼쪽부터, RIGHT는 오른쪽부터 n개만큼 추출하는 함수이다.
- 파이썬의 슬라이싱으로 보면 되겠다.
SELECT UPPER('John') AS up, LOWER('JOHN') AS low
- UPPER는 모두 대문자로, LOWER는 모두 소문자로 변환한다.
- 영문 대소문자로 인한 오류를 없애기 위해 사용함
- 만약 programmers라는 값을 갖는 데이터가 있을 때, programmers라는 값을 갖는 데이터를 count하기 전에 Programmers, PROGRAMMERS와 같이 대소문자만 다른 데이터 모두 lower를 통해 소문자로 변환 후 count해야 원하는 결과가 나올 것이다.
CHAR_LENGTH(name) AS name_length
- CHAR_LENGTH는 특정 컬럼 값의 길이를 반환한다
ROUND(avg(price)) as avg_price
ROUND(avg(price), 2) as avg_price
CEIL(avg(price)) as avg_price
FLOOR(avg(price)) as avg_price
TRUNCATE(avg(price), 2) as avg_price
- ROUND는 반올림, CEIL은 올림, FLOOR는 내림, TRUNCATE는 특정 자릿수 이하를 버림
- ROUND(avg(price),1)과 같이 사용해 반올림 해 줄 자릿수를 정해줄 수 있음
SELECT ABS(price) as res
SELECT MOD(price, product_id) as mods
POW(2, 3)
GREATEST(2,5,1,7,14)
LEAST(2,5,1,7,14)
- MOD는 price를 product_id로 나눈 나머지 값을 반환
- 실무에선 특정 값이 n의 배수인지 확인하기 위해 사용한다.
- product_id는 2의 배수여야한다던지… 등을 확인하기 위해!
- POW는 x의 y승을 반환, GREATEST는 최댓값을 반환, LEAST는 최솟값을 반환한다.
COALESCE(purchase_date, 'Unknown') as purchase_date
- COALESCE는 null 값을 대체하는 함수이다.
- IFNULL(컬럼명, 대체값)을 이용해 NULL 값을 대체할 수도 있음
- 두번째 인자로 컬럼명이 올 수 있음 → null 값을 해당 컬럼의 값으로 채움
DDL, DML
-
테이블: 표 형태로 저장된 데이터 (행과 열로 구성)
-
뷰: 가상의 테이블 (일부분만 본다던지, 다른 테이블과 결합한다던지 할 때 사용)
- SELECT, JOIN 등을 해서 보는 테이블이 뷰인건가?
-
인덱스: 원하는 데이터를 빠르게 찾기위한 목적으로 만드는 색인
-
DDL(Data Definition Language): 데이터베이스 구조를 정의하고 관리
-
CREATE: 테이블/뷰/인덱스 생성
-
ALTER: 테이블/뷰/인덱스 구조 변경
-
DROP: 테이블/뷰/인덱스 삭제

-
IF NOT EXIST를 이용해 ‘products’ 이름의 테이블이 없을 때만 create한다.
-
절대 음수가 입력되지 않는 값은 unsigned로 지정
-
NOT NULL은 해당 컬럼의 값이 NULL 값이 될 수 없음을 의미한다.
-
varchar,char는 최대 길이를 인자로 받는다.
-
primary key는 테이블 내에 모든 행에 적용되는 고유한(unique) 아이디이다.
-
CHARSET을 이용해 테이블의 기본 문자 세트(문자 인코딩 방식)를 지정
-
sql 구문을 콘솔 하나에서 여러개 사용할 떈 세미콜론을 이용해 다른 ddl, dml 구문과 구별한다.
- 왜 어떨 땐 세미콜론을 쓰고 어떨땐 안쓰는지 궁금했는데 이해됐다!
ALTER TABLE product drop column price;
ALTER TABLE product add price int NULL;
ALTER TABLE products modify column price int NULL;
ALTER TABLE products CHANGE price price_2 int;
-
ALTER을 이용해 컬럼을 없애고(drop) 생성하고(add), 수정하고(modify) 컬럼 이름을 변경(CHANGE)할 수 있다.
DROP TABLE products;
-
products 테이블을 삭제한다
-
DML(Data Manipulation Language): 데이터를 쿼리하거나 조작
-
SELECT: 질의
-
INSERT: 삽입
-
UPDATE: 수정
-
DELETE: 삭제

-
테이블에 데이터를 추가

-
특정 조건의 데이터의 값을 변경

-
테이블에서 특정 레코드를 삭제
❗char과 varchar의 차이점

- char는 고정된 공간을 차지
- varchar는 입력되는 데이터에 따라 유동적으로 공간을 차지
- 문자열보다 1 바이트를 더 차지함 (문자열 길이가 함께 저장됨)
- 글자 길이를 계산하는 시간이 있어 데이터 삽입 시 시간이 조금 더 오래 걸릴 수 있다.
- 데이터가 적을 땐 크게 문제되지 않을 수도 있지만, 데이터가 많으면 이 시간이 문제가됨
- 길이가 고정된 문자열의 경우 char 사용, 길이가 유동적일 땐 varchar 이용
궁금한 점
- datetime의 type은 string인가?
- datetime 데이터 유형(DATETIME)이 있다고한다.
- datetime과 문자열의 비교가 가능한가?
- 대부분의 데이터베이스(시스템)가 자동으로 문자열을 데이트타임 타입으로 변환해 비교한다고 함
- DATE_FORMAT의 반환값은 문자열이고 이를 숫자와 비교하기보단 문자열과 비교하는 게 일반적이라고 함
- 몇몇 데이터베이스 시스템에서는 문자열과 숫자 간의 자동 형변환이 발생할 수 있다고 함
- 뷰가 select, join등을 통해 조회한 테이블을 의미하는건가?
CREATE VIEW employee_view AS
SELECT employee_id, first_name, last_name, salary
FROM employees
WHERE department_id = 1;