티스토리 뷰
프로그래머스 풀면서 나오는 SQL 문법 정리 ( ~ 2023.07.09)
& SQL 스터디 얄코 강의 정리
2023.07.09
- like 과 =
- CASE 와 IF문 이용
Lesson1.
RDBMS : Relational Database Management System
Database : 한곳에 저장된 정보들을 원하는 어떤 곳에서든 사용할 수 있는것
특정 소프트웨어나 프로그램에 종속되지 않고 독립된 정보의 집합
-> 여기에 정보들을 집어넣고 원하는 걸 찾아 꺼내는 각종 기능들을 넣으면 DBMS
표 형태에 넣어줘서 데이터의 형식을 맞춰줌 -> SQL : 도메인 특화 언어
데이터 베이스라는 상자 안에 SQL이라는 버튼들을 제공해서 사용자들로 하여금
원하는대로 정보를 넣고 빼고 할 수 있게 해주는 것!
테이블을 분리! - 데이터들이 중복되지 않게 해주어
'고유key'를 통해 테이블들을 JOIN 해줌
관계형 데이터 베이스 'RDBMS' - MySQL , Oracle...
Lesson2. SELECT 기초
* LIMIT : 원하는 만큼만 데이터 가져오기
# LIMIT {가져올 갯수}
SELECT * FROM Customers
LIMIT 10;
# LIMIT {건너뛸 갯수}, {가져올 갯수}
SELECT * FROM Customers
LIMIT 30, 10;
Lesson3. 각종 연산자들
- SQL에선 문자열과 숫자열을 더하면 숫자열을 0으로 인식해버림 but, 숫자로 구성된 문자열은 숫자로 자동인식
SELECT 'ABC' + 3; # 0 +3 = 3
SELECT '1' + '002' * 3; # 1 + 2 + 3 = 6
-- 숫자로 구성된 문자열은 숫자로 자동인식
IS | 양쪽이 모두 TRUE 또는 FALSE |
IS NOT | 한쪽은 TRUE, 한쪽은 FALSE |
- %는 뒤에 글자수 상관없이 무언가가 온다, _(언더바)는 개수만큼 온다!
LIKE '... % ...' | 0~N개 문자를 가진 패턴 |
LIKE '... _ ...' | _ 갯수만큼의 문자를 가진 패턴 |
Lesson4. 숫자와 문자열을 다루는 함수들
- 숫자
CEIL | 올림 |
FLOOR | 내림 |
GREATEST | (괄호 안에서) 가장 큰 값 |
LEAST | (괄호 안에서) 가장 작은 값 |
POW(A, B), POWER(A, B) | A를 B만큼 제곱 |
SQRT | 제곱근 |
TRUNCATE(N, n) | N을 소숫점 n자리까지 선택 |
SELECT
TRUNCATE(1234.5678, 1), # 1234.5
TRUNCATE(1234.5678, 2), # 1234.56
TRUNCATE(1234.5678, 3), # 1234.567
TRUNCATE(1234.5678, -1), # 음수가 들어가면 숫자만큼 소수점 앞으로 0을 붙이게 됨 - 1230
TRUNCATE(1234.5678, -2), # 1200
TRUNCATE(1234.5678, -3); # 1000
- 문자열
UCASE, UPPER | 모두 대문자로 |
LCASE, LOWER | 모두 소문자로 |
CONCAT(...) | 괄호 안의 내용 이어붙임 |
CONCAT_WS(S, ...) | 괄호 안의 내용 S로 이어붙임 |
SELECT CONCAT_WS('-', 2021, 8, 15, 'AM') # 2021-8-15-AM
SELECT
CONCAT_WS(' ', FirstName, LastName) AS FullName # Davollo
FROM Employees;
SUBSTR, SUBSTRING | 주어진 값에 따라 문자열 자름 |
LEFT | 왼쪽부터 N글자 |
RIGHT | 오른쪽부터 N글자 |
SELECT
SUBSTR('ABCDEFG', 3), # 3번째부터 읽는다 - CDEFG
SUBSTR('ABCDEFG', 3, 2), # 3번째부터 2개 읽는다 - CD
SUBSTR('ABCDEFG', -4), # 끝에서 4번째부터 읽는다 - DEFG
SUBSTR('ABCDEFG', -4, 2); # DE
LENGTH | 문자열의 바이트 길이 |
CHAR_LENGTH, CHARACTER_LEGNTH | 문자열의 문자 길이 |
* SQL에선 CHAR_LENGTH를 써야 내가 원하는 한글 글자수를 알 수 있음
TRIM | 양쪽 공백 제거 |
LTRIM | 왼쪽 공백 제거 |
RTRIM | 오른쪽 공백 제거 |
SELECT * FROM Categories
WHERE CategoryName = TRIM(' Beverages ')
LPAD(S, N, P) | S가 N글자가 될 때까지 P를 이어붙임 |
RPAD(S, N, P) | S가 N글자가 될 때까지 P를 이어붙임 |
SELECT
LPAD('ABC', 5, '-'), # 5글자가 될 때까지 왼쪽에 이어붙이기 # --ABC
RPAD('ABC', 5, '-'); # 5글자가 될 때까지 오른쪽에 이어붙이기 # ABC--
REPLACE(S, A, B) | S중 A를 B로 변경 |
SELECT
REPLACE('맥도날드에서 맥도날드 햄버거를 먹었다.', '맥도날드', '버거킹');
INSTR(S, s) | S중 s의 첫 위치 반환, 없을 시 0 |
SELECT
INSTR('ABCDE', 'ABC'), #1
INSTR('ABCDE', 'BCDE'), #2
INSTR('ABCDE', 'C'), #3
INSTR('ABCDE', 'DE'), #4
INSTR('ABCDE', 'F'); #0 - 없으므로 0 반환
SELECT * FROM Customers
WHERE INSTR(CustomerName, ' ') BETWEEN 1 AND 6; # 1에서 6사이에 있는 space를 찾고 싶다
-- < 6으로 하면? #
CAST(A AS T) | A를 T 자료형으로 변환 |
CONVERT(A, T) | A를 T 자료형으로 변환 |
SELECT
'01' = '1',
CAST('01' AS DECIMAL) = CAST('1' AS DECIMAL);
SELECT
'01' = '1',
CONVERT('01', DECIMAL) = CONVERT('1', DECIMAL);
Lesson4-2. 시간/날짜 관련 및 기타 함수들
CURRENT_DATE, CURDATE | 현재 날짜 반환 |
CURRENT_TIME, CURTIME | 현재 시간 반환 |
CURRENT_TIMESTAMP, NOW | 현재 시간과 날짜 반환 |
WEEKDAY | 주어진 DATETIME값의 요일값 반환(월요일: 0) |
ADDDATE, DATE_ADD | 시간/날짜 더하기 |
SUBDATE, DATE_SUB | 시간/날짜 빼기 |
SELECT
ADDDATE('2021-06-20', INTERVAL 1 YEAR),
ADDDATE('2021-06-20', INTERVAL -2 MONTH),
ADDDATE('2021-06-20', INTERVAL 3 WEEK),
ADDDATE('2021-06-20', INTERVAL -4 DAY),
ADDDATE('2021-06-20', INTERVAL -5 MINUTE),
ADDDATE('2021-06-20 13:01:12', INTERVAL 6 SECOND);
DATE_FORMAT⭐⭐⭐ | 시간/날짜를 지정한 형식으로 반환 |
%Y | 년도 4자리 |
%y | 년도 2자리 |
%M | 월 영문 |
%m | 월 숫자 |
%D | 일 영문(1st, 2nd, 3rd...) |
%d, %e | 일 숫자 (01 ~ 31) |
%T | hh:mm:ss |
%r | hh:mm:ss AM/PM |
%H, %k | 시 (~23) |
%h, %l | 시 (~12) |
%i | 분 |
%S, %s | 초 |
%p | AM/PM |
SELECT
DATE_FORMAT(NOW(), '%M %D, %Y %T'),
DATE_FORMAT(NOW(), '%y-%m-%d %h:%i:%s %p'),
DATE_FORMAT(NOW(), '%Y년 %m월 %d일 %p %h시 %i분 %s초');
STR _ TO _ DATE(S, F) | S를 F형식으로 해석하여 시간/날짜 생성 |
* 기타
IFNULL(A, B) | A가 NULL일 시 B 출력 |
Lesson5. 조건에 따라 그룹으로 묶기
- GROUP BY, GROUP BY에 집계함수 사용
- WITH ROLLUP : 전체 집계값을 추가해줌! 총계 추가해주는 기능
SELECT
Country, COUNT(*)
FROM Suppliers
GROUP BY Country
WITH ROLLUP;
* ROLL UP은 ORDER BY와 함께 사용할 수 없음!
- HAVING : 그룹화된 데이터 걸러내기
SELECT
Country, COUNT(*) AS Count
FROM Suppliers
GROUP BY Country
HAVING Count >= 3;
* WHERE는 그룹하기 전 데이터, HAVING은 그룹 후 집계에 사용!
- DISTINCT : 중복된 값 제거
* GROUP BY와 달리 집계함수 사용x, GROUP BY와 달리 정렬하지 않으므로 더 빠름!
SELECT
Country,
COUNT(DISTINCT CITY) # 겹치지 않는 city가 몇개인지
FROM Customers
GROUP BY Country;
CHAPTER2-1. 서브쿼리 ⭐⭐⭐
1. 비상관 서브쿼리 - 서브쿼리와 본 쿼리가 독자적으로 실행되고 있다는 것
SELECT
CategoryID, CategoryName, Description,
(SELECT ProductName FROM Products WHERE ProductID = 1) # Product_id가 1인 ProductName도 가져옴
FROM Categories;
-> 의미 있는 서브쿼리는 아님
# 조건문 안에 들어간 서브쿼리
SELECT * FROM Products
WHERE Price < (
SELECT AVG(Price) FROM Products
);
# 서브쿼리가 조건문 안에 들어감
# 서브쿼리 문이 하나의 행만을 반환할 경우 -> =을 사용해주기
SELECT
CategoryID, CategoryName, Description
FROM Categories
WHERE
CategoryID =
(SELECT CategoryID FROM Products
WHERE ProductName = 'Chais');
# 서브쿼리가 여러개의 행을 반환할 경우 -> IN을 사용해주기
SELECT
CategoryID, CategoryName, Description
FROM Categories
WHERE
CategoryID IN
(SELECT CategoryID FROM Products
WHERE Price > 50);
~ ALL | 서브쿼리의 모든 결과에 대해 ~하다 |
~ ANY | 서브쿼리의 하나 이상의 결과에 대해 ~하다 |
SELECT * FROM Products
WHERE Price > ALL (
SELECT Price FROM Products
WHERE CategoryID = 2
);
2. 상관 서브쿼리 - 서브쿼리가 본 쿼리와 맞물림
- 테이블들의 별칭이 들어감
SELECT
ProductID, ProductName,
(
SELECT CategoryName FROM Categories C
WHERE C.CategoryID = P.CategoryID
) AS CategoryName
FROM Products P;
# product에서 id와 name을 가져오는데
# category 테이블에서 카테고리 id가 product 테이블의 카테고리 id와 같은 것들을 가져와라!
# 정규화로 분리되었던 테이블들을 연결 - 이제 제품명과 한 테이블을 같이 볼 수 있음
# JOIN을 이용해서도 가능
SELECT
CategoryID, CategoryName,
(
SELECT MAX(Price) FROM Products P
WHERE P.CategoryID = C.CategoryID
) AS MaximumPrice,
(
SELECT AVG(Price) FROM Products P
WHERE P.CategoryID = C.CategoryID
) AS AveragePrice
FROM Categories C;
# 각 카테고리에 속한 최고값과 평균값 가져오기
SELECT
ProductID, ProductName, CategoryID, Price
-- ,(SELECT AVG(Price) FROM Products P2
-- WHERE P2.CategoryID = P1.CategoryID)
FROM Products P1
WHERE Price < (
SELECT AVG(Price) FROM Products P2
WHERE P2.CategoryID = P1.CategoryID
);
# 같은 테이블에서 각 카테고리별 평균값보다 가격이 낮은 것들만 가져오기
# 주석처리 빼면 평균값도 같이
EXISTS / NOT EXISTS 연산자
SELECT
CategoryID, CategoryName
-- ,(SELECT MAX(P.Price) FROM Products P
-- WHERE P.CategoryID = C.CategoryID
-- ) AS MaxPrice
FROM Categories C
WHERE EXISTS (
SELECT * FROM Products P
WHERE P.CategoryID = C.CategoryID
AND P.Price > 80
);
# 가격이 80이 넘는 애들만 가져오기
# 주석부분, 카테고리별 max price도 가져오기
CHAPTER2-2. JOIN ⭐⭐⭐⭐⭐
1. JOIN(INNER JOIN) - 양쪽 모두에 값이 있는 행 반환
SELECT C.CategoryID, C.CategoryName, P.ProductName
FROM Categories C
JOIN Products P
ON C.CategoryID = P.CategoryID;
-- ambiguous 주의! => 테이블 별칭 주의하기
# 여러개의 테이블도 JOIN이 가능하다!
SELECT
C.CategoryID, C.CategoryName,
P.ProductName,
O.OrderDate,
D.Quantity
FROM Categories C
JOIN Products P
ON C.CategoryID = P.CategoryID
JOIN OrderDetails D
ON P.ProductID = D.ProductID
JOIN Orders O
ON O.OrderID = D.OrderID;
SELECT
C.CategoryName,
MIN(O.OrderDate) AS FirstOrder,
MAX(O.OrderDate) AS LastOrder,
SUM(D.Quantity) AS TotalQuantity
FROM Categories C
JOIN Products P
ON C.CategoryID = P.CategoryID
JOIN OrderDetails D
ON P.ProductID = D.ProductID
JOIN Orders O
ON O.OrderID = D.OrderID
GROUP BY C.CategoryID;
# 통계량 사용
- 서브쿼리를 쓸 때보다 더 빠르게 계산이 가능하다
# SELF- JOIN (같은 테이블끼리 JOIN)
SELECT
E1.EmployeeID, CONCAT_WS(' ', E1.FirstName, E1.LastName) AS Employee,
E2.EmployeeID, CONCAT_WS(' ', E2.FirstName, E2.LastName) AS NextEmployee
FROM Employees E1 JOIN Employees E2
ON E1.EmployeeID + 1 = E2.EmployeeID;
# 각각의 employee 마다 그 다음 employee들이 누구인지 한행에서 알고 싶을 때!
-- 1번의 전, 마지막 번호의 다음은? : 1번은 이전 id가 없고, 마지막 번호는 그 다음 id가 없다
- 이 경우, INNER JOIN 사용하므로, 테이블에 없는 값은 가져오지 않ㄴ음!
2. LEFT/RIGHT OUTER JOIN - 외부조인
- 반대쪽에 데이터가 있든 없든, 선택된 방향에 있으면 출력!
3. CROSS JOIN - 조건 없이 모든 결과 반환
CHAPTER2-3. UNION
- JOIN은 좌우로 합치는 거라면, UNION은 위 아래로 합침
UNION | 중복을 제거한 집합 |
UNION ALL | 중복을 제거하지 않은 집합 |
- 중복된 것까지 가져오려면 UNION ALL을 이용해야 한다!
교집합
SELECT CategoryID AS ID
FROM Categories C, Employees E
WHERE
C.CategoryID > 4
AND E.EmployeeID % 2 = 0
AND C.CategoryID = E.EmployeeID;
차집합
SELECT CategoryID AS ID
FROM Categories
WHERE
CategoryID > 4
AND CategoryID NOT IN (
SELECT EmployeeID
FROM Employees
WHERE EmployeeID % 2 = 0
);
# NOT IN -
대칭차집합
SELECT ID FROM (
SELECT CategoryID AS ID FROM Categories
WHERE CategoryID > 4
UNION ALL
SELECT EmployeeID AS ID FROM Employees
WHERE EmployeeID % 2 = 0
) AS Temp
GROUP BY ID HAVING COUNT(*) = 1;
# UNION ALL로 중복포함 합쳐줌 - 중복부분은 2개가 나오게 됨!
# HABING 이용해서 1개 있는 것들만 걸러주기 - 대칭차집합
LESSON3. 데이터 조작하기
CREATE TABLE : 테이블 만들기
CREATE TABLE people (
person_id INT,
person_name VARCHAR(10),
age TINYINT,
birthday DATE
);
ALTER TABLE : 테이블 변경
-- 테이블명 변경 - friends로 이름 바꾸기
ALTER TABLE people RENAME TO friends,
-- 컬럼 자료형 변경 - 이름은 똑같고, 자료형 바꾸기
CHANGE COLUMN person_id person_id TINYINT,
-- 컬럼명 변경 - 자료형 똑같고, 이름 바꾸기
CHANGE COLUMN person_name person_nickname VARCHAR(10),
-- 컬럼 삭제 -DROP
DROP COLUMN birthday,
-- 컬럼 추가 - ADD
ADD COLUMN is_married TINYINT AFTER age;
DROP TABLE : 테이블 삭제
DROP TABLE friends;
INSERT INTO : 데이터 삽입
-- 여러 행을 한 번에 입력 가능
INSERT INTO people
(person_id, person_name, age, birthday)
VALUES
(4, '존 스미스', 30, '1991-03-01'),
(5, '루피 D. 몽키', 15, '2006-12-07'),
(6, '황비홍', 24, '1997-10-30');
* 테이블 생성 시 제약 조건
AUTO_INCREMENT | 새 행 생성시마다 자동으로 1씩 증가 |
PRIMARY KEY | 중복 입력 불가, NULL(빈 값) 불가 |
UNIQUE | 중복 입력 불가 |
NOT NULL | NULL(빈 값) 입력 불가 |
UNSIGNED | (숫자일시) 양수만 가능 |
DEFAULT | 값 입력이 없을 시 기본값 |
PRIMARY KEY : 각 행들이 구분 될 수 있는 고유값, 인덱스 생성, 보통 AUTO INCREMENT와 함께 생성
* 자료형
1. 숫자 자료형
- 정수
TINYINT | 1 | -128 ~ 127 | 0 ~ 255 |
SMALLINT | 2 | -32,768 ~ 32,767 | 0 ~ 65,535 |
MEDIUMINT | 3 | -8,388,608 ~ 8,388,607 | 0 ~ 16,777,215 |
INT | 4 | -2,147,483,648 ~ 2,147,483,647 | 0 ~ 4,294,967,295 |
BIGINT | 8 | -2^63 ~ 2^63 - 1 | 0 ~ 2^64 - 1 |
- 고정 소수점 : 좁은 범위의 수 표현 가능, 정확한 값
DECIMAL( s, d ) | 실수 부분 총 자릿수( s ) & 소수 부분 자릿수 ( d ) | s 최대 65 |
- 부동 소수점 : 넓은 범위의 수 표현 가능, 정확하지 않은 값
FLOAT | -3.402...E+38 ~ -1.175...E-38 , 0 , 1.175...E-38 ~ 3.402...E+38 |
DOUBLE | -1.797...E+308 ~ -2.225E-308 , 0 , 2.225...E-308 ~ 1.797...E+308 |
2. 문자 자료형
CHAR( s ) | 고정 사이즈 (남는 글자 스페이스로 채움) | s (고정값) | 255 |
VARCHAR ( s ) | 가변 사이즈 | 실제 글자 수[최대 s] + 1 [글자수 정보] | 65,535 |
- 검색시 CHAR가 더 빠름
- VARCHAR 길이값이 4보다 적으면 CHAR로 자동변환
TINYTEXT | 255 |
TEXT | 65,535 |
MEDIUMTEXT | 16,777,215 |
LONGTEXT | 4,294,967,295 |
3. 시간자료형
DATE | YYYY-MM-DD | |
TIME | HHH:MI:SS | HHH: -838 ~ 838까지의 시간 |
DATETIME | YYYY-MM-DD HH:MI:SS | 입력된 시간을 그 값 자체로 저장 |
TIMESTAMP | YYYY-MM-DD HH:MI:SS | MySQL이 설치된 컴퓨터의 시간대를 기준으로 저장 |
1. DELETE : 주어진 조건의 행 삭제하기
DELETE FROM businesses
WHERE status = 'CLS';
DELETE FROM businesses; # WHERE문 안 쓰면 행 전체 삭제
- DELETE로 지웠을 때는 AUTO_INCREMENT값이 그 전 삭제한 거에서 이어짐...
- 마지막에 어떤 행이 있었는지 기억
2. TRUNCATE : 삭제하면서 테이블 초기화
- TRUNCATE는 AUTO_INCREMENT값 안 이어짐
3. UPDATE : 주어진 조건의 행 수정하기
UPDATE menus
SET menu_name = '삼선짜장'
WHERE menu_id = 12;
UPDATE menus
SET menu_name = CONCAT('전통 ', menu_name)
WHERE fk_business_id IN (
SELECT business_id
FROM sections S
LEFT JOIN businesses B
ON S.section_id = B.fk_section_id
WHERE section_name = '한식'
);
- UPDATE문도 WHERE문 안 넣으면 전부 다 바꿔버리니까 조심하기!!!
참고자료 : MySQL | 얄코 (yalco.kr)
'SQL' 카테고리의 다른 글
[Programmers] Lv2. 재구매가 일어난 상품과 회원 리스트 구하기 (0) | 2023.07.11 |
---|---|
[Programmers] Lv2. 이름에 el이 들어가는 동물 찾기 (0) | 2023.07.11 |
[Programmers] Lv2. 조건에 맞는 도서와 저자 리스트 출력하기 (0) | 2023.07.09 |
[Programmers] Lv2. 가격대 별 상품 개수 구하기 (0) | 2023.07.09 |
[Programmers] Lv2. 조건에 부합하는 중고거래 상태 조회하기 (0) | 2023.07.09 |
- Total
- Today
- Yesterday
- Lagrange Multipler
- 하나의 테이블에 대한 조작
- reranker 속도 개선
- NULL인 열 만들어주기
- llm reranker
- WHERE문 집계함수
- NULL AS
- ORDER BY LIMIT
- cold-start
- pointwise reranker
- 추천시스템
- SQL레시피
- 서브쿼리
- treer구조
- SELECT문 안 서브쿼리
- SET문
- 하이브리드 필터링
- 고전적 추천 알고리즘
- 이코테
- SASRec
- SQL
- 다중 GROUP BY
- groupby 다중
- 여러개 값에 대한 조작
- 알고리즘
- rag 다중문서 활용
- WHERE절서브쿼리
- 연관규칙분석
- reranker
- 숨겨진조건
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |