일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 알고리즘
- 백준
- HTTP
- BFS
- dp
- ip
- 타입 챌린지
- 자바스크립트
- 소켓
- 그래프
- 프로그래머스
- 가천대
- 타입스크립트
- 문자열
- socket
- 쉬운 문제
- HTTP 완벽 가이드
- 레벨 1
- Algorithm
- 크롤링
- Crawling
- javascript
- 수학
- TCP
- type challenge
- Node.js
- 프로그래머스 레벨 2
- dfs
- Nestjs
- typescript
- Today
- Total
kakasoo
[Postgresql] WITH statement 본문
SQL을 작성하다보면 계속해서 반복되는 쿼리가 발생
한다.
sub query에서 outer query에 접근하지 못하거나, 그 외에도 많은 경우에 동일한 쿼리를 짜야할 때가 있다.
이런 동일 쿼리가 발생할 경우, 작성도 어렵거니와 쿼리를 수정할 때 반복된 모든 구간에서의 수정이 필요하다.
따라서 이런 쿼리를 더 쉽고 간편하게 작성하기 위해서, 변수와 같이 쿼리를 저장
해둘 필요가 있다.
그럴 때 사용하는 것이 바로 WITH 문
이다.
WITH의 사용 예시
WITH cte AS (
SELECT column1, column2, column3
FROM table1
WHERE column1 = 'some value'
)
SELECT *
FROM cte
WHERE column2 = 'another value';
이런 식으로 WITH 다음에 alias를 작성하고, 그 후에 AS 문으로 어떤 쿼리인지를 보여주면 된다.
이후 미리 잡은 alias로 해당 쿼리를 간편하게 호출할 수 있다.
일반적인 AS 문이, 작성된 쿼리를 호출하기 위해서 명명하는 거였기에, 이 구문이 특이하게 보인다.
이제 이를 활용한 복잡한 예시를 한 번 봐보자.
WITH cte AS (
SELECT
sub. "week",
COUNT(*)
FROM (
SELECT
DATE_TRUNC('week', oi. "createdAt") AS "week", oi. "companyId"
FROM
order_info AS oi
GROUP BY
DATE_TRUNC('week', oi. "createdAt"), oi. "companyId"
ORDER BY
DATE_TRUNC('week', oi. "createdAt") DESC) AS sub
GROUP BY
sub. "week"
ORDER BY
sub. "week" ASC
)
SELECT MIN(cte."week") AS "first week to archieve", 10 AS "count" FROM cte WHERE cte."count" >= 10
여기서 의도하고 있는 것은 주문서 ( = order_info ) 가 생성된 주간이 같은 날짜들로 그룹화한 다음,
주문이 들어온 날짜 ( = createdAt ) 가 동일한 주문서의 회사 아이디 ( = companyId ) 를 뽑고,
다시 그 주간으로 그룹화하여 회사의 수를 구한 cte ( = common table expression
의 약자 ) 를 구한 것이다.
이렇게 만들어진 cte 를 이제, 원할 때 호출해서 더 편리한 쿼리를 작성할 수 있게 되었다.
아래의 SELECT 문은 주문서의 회사 수가 10개가 된 첫 번째 주간을 구하는 쿼리다.
만약 20번째 회사가 우리 서비스를 결제한 시점, 30번째 회사가 우리 서비스를 결제한 시점을 알고 싶다면?
SELECT MIN(cte."week") AS "first week to archieve", 10 AS "count" FROM cte WHERE cte."count" >= 10;
SELECT MIN(cte."week") AS "first week to archieve", 20 AS "count" FROM cte WHERE cte."count" >= 20;
SELECT MIN(cte."week") AS "first week to archieve", 30 AS "count" FROM cte WHERE cte."count" >= 30;
이렇게 호출하는 것만으로도 간단하게 된다.
앞서 배운 것과 같이, UNION ALL문을 WITH문과 함께 사용하면 더 깔끔한 출력 결과를 볼 수 있다.
SELECT MIN(cte."week") AS "first week to archieve", 10 AS "count" FROM cte WHERE cte."count" >= 10;
UNION ALL SELECT MIN(cte."week") AS "first week to archieve", 20 AS "count" FROM cte WHERE cte."count" >= 20;
UNION ALL SELECT MIN(cte."week") AS "first week to archieve", 30 AS "count" FROM cte WHERE cte."count" >= 30;
'프로그래밍 > SQL' 카테고리의 다른 글
[Postgresql] 문자열 합치기 & 가공하기 (0) | 2023.01.06 |
---|---|
[Postgresql] 일련의 연속적인 날짜 구하기 (0) | 2023.01.01 |
[Postgresql] DATE_TRUNC 날짜 자르기 (0) | 2022.12.22 |
[Postgresql] TO_CHAR로 날짜 다루기 (0) | 2022.12.22 |
[Postgresql] UNION (0) | 2022.12.22 |