SQL 기본문법 > 서브쿼리(SubQuery) - 사용 위치에 따른 서브쿼리

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


서브쿼리(SubQuery)

SQL문 내부에서 사용하는 SELECT문

서브쿼리는 WHERE, SELECT, FROM, HAVING절 안에 넣어 사용할 수 있고, 이러한 서브쿼리는 괄호안에 적어주어야 한다. 일반적으로 서브쿼리가 먼저 실행된 후 메인쿼리가 실행되는 순서로 작업이 이루어진다.

조건절에서 사용하는 서브쿼리

-- 문제: 고객 전체의 평균 마일리지보다 평균마일리지가 큰 도시에 대해
-- 도시명과 도시의 평균 마일리지를 보이시오
SELECT 도시, AVG(마일리지) 평균마일리지 FROM 고객 GROUP BY 1
HAVING AVG(마일리지) > (SELECT AVG(마일리지) FROM 고객);

INLINE VIEW

FROM 절에서 사용하는 서브쿼리

이때 뷰에는 별명을 지정해줘야하며, 인라인뷰의 별명은 테이블명처럼 사용가능하다.

-- 문제: 담당자명, 고객회사명, 마일리지, 도시, 해당도시의 평균 마일리지를 보이시오
-- 그리고 고객이 위치하는 도시의 평균 마일리지와 각 고객의 마일리지 간 차이도 함께 보이시오
SELECT 담당자명, 고객회사명, 마일리지, 고객.도시, 도시_평균마일리지, (도시_평균마일리지-마일리지) 차이 FROM 고객,
(SELECT 도시, AVG(마일리지)  as '도시_평균마일리지' FROM 고객 GROUP BY 1) as 도시별요약 
WHERE 고객.도시 = 도시별요약.도시;

Scalar SubQuery(스칼라서브쿼리)

SELECT 절에서 사용하는 서브쿼리

서브쿼리의 값이 딱 1개의 값으로 도출되어야 하는 서브쿼리로 이 쿼리를 통해 반환되는 값을 메인쿼리에서 사용한다. 이때 서브쿼리의 결과로 행을 0개 반환한다면 메인쿼리의 결과는 null이고 2개 이상의 행이 반환된다면 오류가 발생한다.

-- 문제1: 고객번호, 담당자명과 고객의 최종 주문일을 보이시오
SELECT 고객번호, 담당자명, 
(SELECT MAX(주문일) 최종주문일 FROM 주문 WHERE 고객.고객번호 = 주문.고객번호) AS 최종주문일
FROM 고객;

CTE(Common Table Expression)

쿼리로 만든 임시데이터셋으로 WITH에서 정의

쿼리 내에서 여러번 참조가 가능하기때문에 재사용성이 좋으며, 하나의 쿼리를 논리적 블록으로 나눌 수 있어 가독성이 좋다.

-- 문제: 담당자명, 고객회사명, 마일리지, 도시, 해당도시의 평균 마일리지를 보이시오
-- 그리고 고객이 위치하는 도시의 평균 마일리지와 각 고객의 마일리지 간 차이도 함께 보이시오
-- 이를 CTE로 풀이하시오 
SELECT 담당자명, 고객회사명, 마일리지, 고객.도시, 도시_평균마일리지, (도시_평균마일리지-마일리지) 차이 FROM 고객,
(SELECT 도시, AVG(마일리지) as '도시_평균마일리지' FROM 고객 GROUP BY 1) as 도시별요약 
WHERE 고객.도시 = 도시별요약.도시;

-- CTE
WITH 도시별요약 AS (
    SELECT 도시, AVG(마일리지) AS 도시_평균마일리지
    FROM 고객
    GROUP BY 1
)

SELECT 담당자명, 고객회사명, 도시_평균마일리지, (도시_평균마일리지-마일리지) 차이 
FROM 고객, 도시별요약
WHERE 고객.도시 = 도시별요약.도시;

SQL 기본문법 > JOIN(CROSS, INNER, OUTER, SELF)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


JOIN

하나의 테이블에 원하는 데이터가 모두 있다면 좋겠지만, 두 개의 테이블을 엮어야 원하는 결과가 나오는 경우도 많다. 이때 조인을 쓰면 두개의 테이블을 엮어 원하는 데이터를 추출할 수 있게 한다. 즉 조인이란,

  1. 두 개 이상의 테이블을 연결하여 데이터를 검색하는 방법
  2. 서로 다른 테이블에 저장된 데이터를 함께 가져와 하나의 결과로 표시함
  3. 검색하고 싶은 컬럼이 서로 다른 테이블에 있을 때 사용
  4. 조인을 사용해 여러개의 테이블을 마치 하나의 테이블처럼 사용 가능

조인 방식

  • ANSI SQL
    • FROM 절 안의 두 테이블 사이에 조인 종류(CROSS, INNER, OUTER)에 따라 JOIN 키워드를 넣어줌
    • ON 절에 조인에 대한 조건을 작성하고 나머지 조건은 WHERE 절에 작성
    • CROSS, INNER, OUTER 키워드는 생략 가능
  • Non-ANSI SQL
    • FROM 절에 테이블을 쉼표로 구분해 작성
    • 조인조건, 기타조건을 구분없이 WHERE절에 작성

CROSS JOIN

한 쪽 테이블의 각 행마다 다른 쪽 테이블의 모든 행이 각각 한번씩 매칭되는 조인 (Cartesian Product)

-- 문제1: 사원테이블과 부서테이블을 조인하여 배재용 사원에 대한 정보를 보이시오
-- 이름, 사원테이블의 부서번호, 부서테이블의 부서번호, 부서명
SELECT 사원.이름, 사원.부서번호, 부서.부서번호, 부서.부서명 FROM 사원 JOIN 부서
ON 사원.이름 = '배재용'; 

SELECT 사원.이름, 사원.부서번호, 부서.부서번호, 부서.부서명 FROM 사원,부서
WHERE 사원.이름 = '배재용'; 

INNER JOIN

각 테이블에서 조인 조건에 일치되는 데이터만 가져오는 조인

여러 테이블을 사용할 때 조인조건을 제대로 기술하지 않으면 크로스조인을 한 결과가 나온다

-- 문제1: 이소미 사원의 사원번호, 직위, 부서번호, 부서명을 보이시오
SELECT 사원.이름, 사원.사원번호, 사원.직위, 부서.부서번호, 부서.부서명 FROM 사원 INNER JOIN 부서 
ON 사원.부서번호 = 부서.부서번호  
WHERE 사원.이름 = '이소미';

-- 문제2: 고객 회사들이 주문한 주문건수를 주문건수가 많은 순서대로 보이시오
-- 이때 고객회사의 정보로 고객번호, 담당자명, 고객회사명을 보이시오
SELECT 고객.고객번호, 고객.담당자명, 고객.고객회사명, count(*) 주문건수 FROM 고객 INNER JOIN 주문
ON 고객.고객번호 = 주문.고객번호 
GROUP BY 1
ORDER BY 주문건수 desc;

-- 문제3: 고객별 주문금액 합을 보이되, 주문 금액 합이 많은 순서대로 보이시오
-- 이때 고객회사의 정보로 고객번호, 담당자명, 고객회사명을 보이시오
SELECT 고객.고객번호, 고객.담당자명, 고객.고객회사명, SUM(주문수량*단가) 주문합  
FROM 고객 
INNER JOIN 주문
ON 고객.고객번호 = 주문.고객번호 
INNER JOIN 주문세부
ON 주문.주문번호 = 주문세부.주문번호 
GROUP BY 1
ORDER BY 주문합 desc;

-- 문제4: 고객 테이블에서 담당자가 이은광인 경우 
-- 고객번호, 고객회사명, 담당자명, 마일리지와 마일리지 등급을 보이시오
-- *공통된 컬럼이 없는데, 조인을 하는 예외적인 방법*
SELECT 고객.고객번호, 고객.담당자명, 고객.마일리지, 마일리지, 등급명  
FROM 고객 
INNER JOIN 마일리지등급 M  -- alias 
ON 마일리지등급 BETWEEN 하한마일리지 AND 상한마일리지  -- 이렇게 join에 대한 조건 작성 가능 
WHERE 담당자명 = '이은광';

OUTER JOIN

조건이 맞지 않는 행도 함께 출력할 수 있음. 외부 조인은 두 테이블에서 한쪽에는 데이터가 있고, 한쪽에는 없는 경우 데이터가 있는 쪽의 테이블을 기준으로 데이터를 출력한다. MySQL에서 외부조긴은 ANSI SQL 방식으로만 표현 가능!

이너조인은 양쪽 모두 데이터가 있어야 가능하지만, 외부조인은 한쪽에 데이터가 없더라도 조인이 가능하다. 이때 없는 데이터에 대해서는 모두 null로 채워진다. 따라서 외부조인을 사용할 때 어느쪽 방향으로 조인을 해주는 지 설정하는 것이 중요하다. (데이터가 많은 쪽으로 조인을 해주는 것이 옳다) 이런 것들을 잘하기 위해서는 각 테이블과 컬럼, 각 데이터들간의 관계를 잘 알아야한다.

OUTER는 생략가능

  • LEFT JOIN
    • 왼쪽에 있는 테이블의 결과를 기준으로 오른쪽 테이블 데이터 매칭
    • 매칭되는 데이터가 없는 경우에는 null로 표시
  • RIGHT JOIN
    • 오른쪽에 있는 테이블의 결과를 기준으로 왼쪽 테이블 데이터 매칭
    • 매칭되는 데이터가 없는 경우에는 null로 표시

외부조인을 사용할때 별도의 방향을 정해주지 않으면 FULL OUTER JOIN이 된다는 것을 잊지말자.

-- 문제: 사원번호, 이름, 부서명을 출력하는데, 성별이 여자인 사람을 출력 
SELECT 사원번호, 이름, 부서명 FROM 사원 
LEFT JOIN 부서 ON 사원.부서번호 = 부서.부서번호 
WHERE 성별 = '여';

위 문제의 경우, 사원 테이블에는 부서번호, 사원번호, 이름, 성별 컬럼이 존재하고, 부서 테이블에는 부서번호, 부서명이 존재했다. 따라서 부서 테이블을 사원테이블에 조인시키고 각 테이블은 공통된 부서번호로 연결시켰다. 이때 아래 이미지를 보면 부서명이 존재하지 않는 사원에 대해서도 null이 들어감으로써 테이블이 제대로 만들어진 것을 볼 수 있다. 이렇듯 데이터가 존재하지 않아도 조인을 하기 위해서 외부조인을 사용하는 것을 알 수 있다.

즉, 부서명이 없는 정수진이라는 사람의 데이터도 얻기 위해서는 외부조인을 사용해야한다.

-- 문제: 부서명과 해당 부서의 소속사원 정보를 보이시오.
-- 이때 사원이 한명도 존재하지 않는 부서명이 있다면 그 부서명도 보이시오.
SELECT * FROM 부서 LEFT JOIN 사원  
ON 사원.부서번호 = 부서.부서번호;

없는 사원에 대한 데이터까지 보고싶은 것이기 때문에 부서에 대해 사원을 외부 조인 해줘야 한다.

그렇다면 사원이 없는 부서만 뽑아내려면 어떻게 해야할까?

SELECT * FROM 사원 LEFT JOIN 부서  
ON 사원.부서번호 = 부서.부서번호
WHERE 부서명 IS NULL;

SELECT * FROM 부서 LEFT JOIN 사원  
ON 사원.부서번호 = 부서.부서번호
WHERE 이름 IS NULL;

이렇듯 원하는 기준이 무엇이냐에 따라 어느쪽으로 조인을 할지 잘 선택하는 것이 중요하다. 그리고 그 방향을 설정하고 난 다음에는 데이터를 어떻게 뽑아올 지 잘 고민해봐야할 것 같다. 별개로 위에서 또 중요한 점은 is null을 사용했다는 것이다. 외부조인에 is null을 사용함으로서 겹치는 영역이 없는 한쪽 테이블의 값을 가져올 수도 있다.

이 이미지를 잊지말자.

SELF JOIN

동일한 테이블 내에서 한 컬럼이 다른 컬럼을 참조하는 조인

동일한 테이블명이 조인조건에 두번 나타나는 것이 특징으로, 이때 테이블명을 다른 별명으로 지정해 다른 테이블인 것처럼 사용한다. 이때 컬럼명도 동일하기 때문에 컬럼명 또한 별명을 지어줌으로써 컬럼의 소속 또한 구분해주어야 한다.

-- 문제1: 사원번호, 사원의 이름, 상사의 사원번호, 상사의 이름을 보이시오
SELECT 사원.사원번호, 사원.이름, 상사.사원번호 as 상사번호, 상사.이름 as 상사이름 FROM 사원, 사원 AS 상사
WHERE 상사.사원번호 = 사원.상사번호; 

-- 문제2: 사원이름, 직위, 상사이름을 상사이름 순으로 정렬하여 나타내시오.
-- 이때 상사가 없는 사원의 이름도 함께 보이시오 

SQL 함수 사용하기 (집계함수)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


집계 함수

여러 행에 걸쳐 있는 값을 묶어서 계산을 수행하여 단일 값을 반환하는 함수

  • COUNT(): 레코드의 개수 계산
  • SUM(): 합
  • AVG(): 평균
  • MAX(): 최대값
  • MIN(): 최소값
  • STDDEV(): 표준편차

집계함수의 활용 1. WHERE절

WHERE 절에 조건을 넣으면 조건에 맞는 레코드에 한해 값을 요약

-- 고객테이블에서 '서울특별시' 고객에 대해 마일리지합, 평균, 최소, 최대값을 조회
SELECT SUM(마일리지), AVG(마일리지), MIN(마일리지), MAX(마일리지) FROM 고객 WHERE 도시 = '서울특별시';

집계함수의 활용 2. GROUP BY절

그룹별로 묶어서 요약할 때 사용

  1. SELECT 절에 그룹으로 묶을 컬럼명과 집계함수를 넣음
  2. SELECT 절의 집계함수를 제외한 나머지 컬럼이나 수식은 반드시 GROUP BY 절에 넣어야 오류발생이 없음
-- 문제1: 고객 테이블에서 도시별 고객의 수와 해당 도시 고객들의 마일리지 평균을 구하시오
SELECT 도시, COUNT(*), AVG(마일리지) FROM 고객
GROUP BY 1;

-- 문제2: 위 문제에서 중복된 도시를 제거한 데이터를 구하시오
SELECT DISTINCT 도시, COUNT(*), AVG(마일리지) FROM 고객
GROUP BY 1;

-- 문제3: 담당자직위별로 묶고, 같은 담당자직위에 대해서는 도시별로 묶어 집계한 결과
-- 고객수와 평균 마일리지를 보이시오. 이떄 담당자직위, 도시순으로 정렬하기 
SELECT 담당자직위, 도시, COUNT(*) 고객수, AVG(마일리지) AS '평균 마일리지' FROM 고객 
GROUP BY 1,2
ORDER BY 1,2 

집계함수의 활용 3. HAVING 절

GROUP BY 결과에 대해 추가 조건을 넣고자 할 때 사용\n 이때 SELECT 절에 있는 컬럼과 함수에 대한 조건만 넣을 수 있다!

-- 문제1: 고객 테이블에서 도시별로 그룹을 묶어 고객수와 평균마일리지를 구하고,
-- 이중에서 고객수가 10명 이상인 레코드만 걸러내시오
SELECT 도시, COUNT(*) 고객수, AVG(마일리지) FROM 고객 
GROUP BY 1
HAVING 고객수 >= 10;

-- 문제2: 고객번호가 T로 시작하는 고객에 대해 도시별로 묶어서 고객의 마일리지를 구하시오
-- 이떄 마일리지의 합이 1000점 이상인 레코드만 보이시오
SELECT 도시, SUM(마일리지) FROM 고객
WHERE 고객번호 LIKE 'T%'
GROUP BY 1
HAVING SUM(마일리지) >= 1000;

집계함수 심화 1. WITH ROLLUP

그룹별 소계와 전체 총계를 한번에 확인하고 싶을 떄 사용\n GROUP BY 절 다음에 WITH ROLLUP을 붙여 사용

-- 문제1: 지역이 null인 고객에 대해 도시별 고객수, 평균 마일리지를 보이시오
-- 이때 마지막 행에 전체 고객수와 전체 고객에 대한 평균 마일리지도 함께 보이시오
SELECT 도시, COUNT(*), AVG(마일리지) FROM 고객 
WHERE 지역 IS NULL
GROUP BY 1 WITH ROLLUP;

-- 문제2: 담당자직위에 마케팅이 들어가있는 고객에 대해 도시별 고객수, 평균 마일리지를 보이시오
-- 담당자직위별 고객수와 전체 고객수도 함꼐 볼수 있도록 조회
SELECT 담당자직위, 도시, COUNT(*), AVG(마일리지) FROM 고객 
WHERE 담당자직위 LIKE '%마케팅%'
GROUP BY 1,2 WITH ROLLUP;

이렇게 마케팅 과장에 대한 고객수 합, 마일리지 평균 & 마케팅 담당에 대한 고객수 합, 마일리지 평균이 총계로 나와있는 것을 확인할 수 있다.

집계함수 심화 2. GROUPING

WITH ROLLUP 결과로 나온 NULL에 대해 1을 반환하고, 그렇지 않으면 0을 반환

-- 문제: 담당자직위가 대표 이사인 고객에 대해 지역별로 묶어 고객수를 보이고 전체고객수를 같이 보이시오
SELECT 지역, COUNT(*) FROM 고객
WHERE 담당자직위 = '대표 이사'
GROUP BY 1 WITH ROLLUP;

이때 결과의 맨위 null은 실제 진짜 데이터상 존재하는 null의 합이고 마지막 null은 WITH ROLLUP을 통해 나온 총계를 의미한다. 이렇듯 각각의 NULL을 구분하기 위해 사용하는 것이 GROUPING이다.

SELECT 지역, COUNT(*), GROUPING(지역) FROM 고객
WHERE 담당자직위 = '대표 이사'
GROUP BY 1 WITH ROLLUP;

이렇게 WITH ROLLUP에 결과로 나온 null 값에는 1, 그렇지 않은 곳에는 0이 적혀있는 것을 볼 수 있다.

집계함수 심화 3. GROUP_CONCAT()

각 행의 값을 결합

-- 문제1: 사원테이블에 있는 이름을 한 행에 나열하시오
SELECT GROUP_CONCAT(이름) FROM 사원;

-- 문제2: 고객테이블에 들어있는 지역을 한행에 나열하되 중복되는 지역은 한번만 보이시오 
SELECT GROUP_CONCAT(distinct 지역) FROM 고객;

-- 문제3: 고객테이블에서 도시별로 고객회사명을 나열하시오
SELECT 도시, GROUP_CONCAT(고객회사명) FROM 고객 
GROUP BY 도시; 

문제를 풀어보자

문제1

주문테이블에서 요청일보다 발송이 늦어진 주문내역이 월별로 몇건씩인지 요약하시오. 이때 주문월 순서대로 정렬하시오

SELECT MONTH(주문일) 주문월, COUNT(*) FROM 주문 
WHERE DATEDIFF(발송일, 요청일) > 0
GROUP BY 1
ORDER BY 1;

문제2

제품 테이블에서 아이스크림 제품들에 대해 제품명별로 재고합을 보이시오

SELECT 제품명, SUM(재고) FROM 제품
WHERE 제품명 LIKE '%아이스크림%'
GROUP BY 1;

문제3

고객테이블에서 마일리지가 50000점 이상인 고객은 vip, 그렇지않으면 일반고객으로 구분하고, 고객구분별로 고객수와 평균 마일리지를 보이시오

SELECT IF(마일리지 >= 50000, 'vip', '일반고객') as 고객등급, COUNT(*), AVG(마일리지) FROM 고객
GROUP BY 고객등급;

SQL 함수 사용하기 (단일 행 함수의 제어/기타 함수)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


형 변환 함수

데이터를 검색, 삽입할 때 컬럼에 맞는 형식으로 지정하지 않으면 오류가 나는 경우 사용하는 함수

CAST

  • CAST(값 as 데이터타입): 원하는 형태로 데이터타입을 변경하여 처리 혹은 확인
-- 문자를 숫자로
SELECT CAST('1' as unsigned);
-- 숫자를 문자로
SELECT CAST(1 as char(1));

제어 흐름 함수

프로그램의 흐름을 제어할 때 사용

IF

  • IF(조건, 수식1, 수식2): 조건 결과가 참이면 수식1 반환, 거짓이면 수식2 반환
-- 제품 테이블에서 단가가 3000 이상이면 '고가', 이하면 '저가'
SELECT IF (단가 >= 3000, '고가', '저가') FROM 제품;

IFNULL, NULLIF

  • IFNULL(수식1, 수식2): 수식1이 null이 아니면 수식1 반환, null이면 수식2 반환 > 결측치 처리
  • NULLIF(수식1, 수식2): 두 값이 같으면 null, 다르면 수식1 반환
SELECT IFNULL(1, 0);  -- 1
SELECT IFNULL(null, 0);  -- 0

SELECT NULLIF(12*10, 120);  -- null
SELECT NULLIF(12*10, 1200);  -- 120

CASE

  • CASE(WHEN 조건1 THEN 결과1 .. ELSE END): 조건 비교가 여러개일때 사용
  • IF문의 확장버전
-- 주문 금액이 5,000원 이상이면 ‘초과달성’, 4,000원 이상이면 ‘달성’ 그 나머지는 ‘미달성’
SELECT 
CASE 
    WHEN 주문금액 >= 5000 THEN '초과달성' 
    WHEN 주문금액 >= 4000 THEN '달성'
    ELSE '미달성'
END
AS '달성여부'

문제를 풀어보자

문제1

고객회사명의 앞 두글자를 **로 변경해보기

SELECT 고객회사명, CONCAT('**', SUBSTR(고객회사명, 3));

문제 2

도시에서 특별시나 광역시는 대도시로, 나머지는 도시로 구분

SELECT 도시, IF(도시 LIKE '%특별시' or 도시 LIKE '%광역시', '대도시', '도시') AS '도시 구분';

문제 3

마일리지가 100점 이상이면 vvip, 50점 이상이면 vip, 이외는 일반고객으로 구분

SELECT 마일리지
CASE   
    WHEN 마일리지 >= 100 THEN 'vvip'
    WHEN 마일리지 >= 50 THEN 'vip'
    ELSE '일반고객'
END

문제4

주문일, 주문년도, 분기, 월, 일, 요일, 한글요일을 조회

SELECT 주문일, YEAR(주문일), QUATER(주문일), MONTH(주문일), DAY(주문일), WEEKDAY(주문일) 요일,
        ELT(DAYOFWEEK(주문일), '일', '월', '화', '수', '목', '금', '토') 한글요일;

SQL 함수 사용하기 (단일 행 함수의 날짜/시간형 함수)

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


날짜/시간형 함수

현재 시간 혹은 시간 데이터를 가공해 정보를 얻을 떄 사용

NOW, SYSDATE, CURDATE, CURTIME

  • NOW(), SYSDATE(): 현재 날짜, 시간을 출력
  • CURDATE(): 현재 날짜를 출력
  • CURTIME(): 현재 시간을 출력
SELECT NOW(), SYSDATE(), CURDATE(), CURTIME();

YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, QUATER

  • YEAR(date), MONTH(date), DAY(date), QUATER(date): 년, 월, 일, 분기
  • HOUR(date), MINUTE(date), SECOND(date): 시, 분, 초
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW()), QUATER(NOW());
SELECT HOUR(NOW()), MINUTE(NOW()), SECOND(NOW());

DATEDIFF, TIMESTAMPDIFF

  • DATEDIFF(끝일자, 시작일자): 기간을 일자 기준으로 반환
  • TIMESTAMPDIFF(단위, 시작일자, 끝일자): 기간을 지정한 단위 기준으로 반환
-- 문제1: 지금 시간으로부터 2000-01-31와의 일 차이
SELECT DATEDIFF(NOW(), '2000-01-31');  -- 9304
SELECT TIMESTAMPDIFF(day, '2000-01-31', NOW());

-- 문제2: 만나이, 태어난지 몇달, 태어난지 몇일
SELECT TIMESTAMPDIFF(year, '2000-01-31', NOW());  -- 25
SELECT TIMESTAMPDIFF(month, '2000-01-31', NOW());  -- 305
SELECT TIMESTAMPDIFF(day, '2000-01-31', NOW());  -- 9304

ADDDATE, SUBDATE

  • ADDDATE(date, interval 기간 단위): 지정한 날짜를 기준으로 그 기간만큼 더한 날짜 반환
  • SUBDATE(date, interval 기간 단위): 지정한 날짜를 기준으로 그 기간만큼 뺀 날짜 반환
SELECT ADDDATE(NOW(), 50);
SELECT ADDDATE(NOW(), interval 50);

-- 오늘날짜로 50일 전
SELECT SUBDATE(NOW(), interval 50 day);

LAST_DAY, DAYOFYEAR, MONTHNAME

  • LAST_DAY(date): 해당월의 마지막 일자 반환
  • DAYOFYEAR(date): 현재 년도에서 몇일이 지났는지 반환
  • MONTHNAME(date): 월을 영문으로 반환
  • WEEKDAY(date): 요일을 정수로 반환
SELECT LAST_DAY('2025-02-03');  -- 2025-02-28
SELECT DAYOFYEAR(NOW());  -- 203
SELECT MONTHNAME(NOW());  -- July
SELECT WEEKDAY(NOW());   -- 1(화요일)