

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# WITH 절
<a name="WITH_clause"></a>

WITH 절은 쿼리에 있는 SELECT 목록에 선행하는 선택적 절입니다. WITH 절은 하나 이상의 *common\$1table\$1expressions*를 정의합니다. 각 공통 테이블 표현식(CTE) 은 뷰 정의와 유사한 임시 테이블을 정의합니다. FROM 절에서 이러한 임시 테이블을 참조할 수 있습니다. 임시 테이블은 자신이 속한 쿼리가 실행되는 동안에만 사용됩니다. WITH 절에 있는 각각의 CTE는 테이블 이름, 열 이름의 선택적 목록, 테이블로 평가되는 쿼리 표현식(SELECT 문)을 지정합니다.

WITH 절 하위 쿼리는 단일 쿼리를 실행하는 내내 사용 가능한 테이블을 정의하는 효율적인 방법입니다. 모든 경우에 있어 SELECT 문의 본문에 하위 쿼리를 사용하여 같은 결과를 얻을 수 있지만, WITH 절 하위 쿼리는 더 간단하게 쓰고 읽을 수 있습니다. 가능한 경우 여러 번 참조되는 WITH 절 하위 쿼리는 공통 하위 표현식으로 최적화됩니다. 즉, WITH 하위 쿼리를 한 번 평가하고 그 결과를 재사용할 수 있습니다. (공통 하위 표현식은 WITH 절에 정의되는 하위 표현식으로 제한되지 않습니다.)

## 구문
<a name="WITH_clause-synopsis"></a>

```
[ WITH common_table_expression [, common_table_expression , ...] ]
```

여기서 *common\$1table\$1expression*은 비재귀적일 수 있습니다. 다음은 비재귀 형식입니다.

```
CTE_table_name AS ( query )
```

## 파라미터
<a name="WITH_clause-parameters"></a>

 *common\$1table\$1expression*   
[FROM 절](FROM_clause30.md)에서 참조할 수 있는 임시 테이블을 정의하고 해당 테이블이 속한 쿼리 실행 중에만 사용됩니다.

 *CTE\$1table\$1name*   
WITH 절 하위 쿼리의 결과를 정의하는 임시 테이블의 고유한 이름입니다. 단일 WITH 절 내에서 중복되는 이름을 사용할 수 없습니다. 각각의 하위 쿼리에는 [FROM 절](FROM_clause30.md)에서 참조될 수 있는 테이블 이름이 주어져야 합니다.

 *query*   
 에서 AWS Clean Rooms 지원하는 모든 SELECT 쿼리입니다. [SELECT](sql-commands-select-spark.md)을(를) 참조하세요.

## 사용 노트
<a name="WITH_clause-usage-notes"></a>

다음 SQL 문에 WITH 절을 사용할 수 있습니다.
+ SELECT, WITH, UNION, UNION ALL, INTERSECT, INTERSECT ALL, EXCEPT 또는 EXCEPT ALL 

WITH 절을 포함한 쿼리의 FROM 절이 WITH 절로 정의되는 테이블 중 참조하지 않는 테이블이 있을 경우 WITH 절이 무시되고 쿼리가 정상적으로 실행됩니다.

WITH 절 하위 쿼리로 정의되는 테이블은 WITH 절이 시작하는 SELECT 쿼리의 범위에서만 참조될 수 있습니다. 예를 들어, SELECT 목록, WHERE 절 또는 HAVING 절에 있는 하위 쿼리의 FROM 절에서 그와 같은 테이블을 참조할 수 있습니다. 하위 쿼리에 WITH 절을 사용할 수 없고 기본 쿼리 또는 다른 하위 쿼리의 FROM 절에서 WITH 절의 테이블을 참조할 수 없습니다. 이 쿼리 패턴으로 인해 WITH 절 테이블에 대해 `relation table_name doesn't exist` 형식의 오류 메시지가 발생합니다.

WITH 절 하위 쿼리 내에서 다른 WITH 절을 지정할 수 없습니다.

WITH 절 하위 쿼리에 의해 정의되는 테이블에 대한 전방 참조를 할 수 없습니다. 예를 들어, 다음 쿼리는 테이블 W1의 정의에서 테이블 W2에 대한 전방 참조 때문에 오류를 반환합니다.

```
with w1 as (select * from w2), w2 as (select * from w1)
select * from sales;
ERROR:  relation "w2" does not exist
```

## 예제
<a name="WITH_clause-examples"></a>

다음 예에서는 WITH 절을 포함하는 쿼리로서 가능한 가장 간단한 사례를 보여줍니다. VENUECOPY라는 이름의 WITH 쿼리는 VENUE 테이블에서 모든 행을 선택합니다. 다음에는 기본 쿼리가 VENUECOPY에서 모든 행을 선택합니다. VENUECOPY 테이블은 이 쿼리의 지속 시간 동안에만 존재합니다.

```
with venuecopy as (select * from venue)
select * from venuecopy order by 1 limit 10;
```

```
 venueid |         venuename          |    venuecity    | venuestate | venueseats
---------+----------------------------+-----------------+------------+------------
1 | Toyota Park                | Bridgeview      | IL         |          0
2 | Columbus Crew Stadium      | Columbus        | OH         |          0
3 | RFK Stadium                | Washington      | DC         |          0
4 | CommunityAmerica Ballpark  | Kansas City     | KS         |          0
5 | Gillette Stadium           | Foxborough      | MA         |      68756
6 | New York Giants Stadium    | East Rutherford | NJ         |      80242
7 | BMO Field                  | Toronto         | ON         |          0
8 | The Home Depot Center      | Carson          | CA         |          0
9 | Dick's Sporting Goods Park | Commerce City   | CO         |          0
v     10 | Pizza Hut Park             | Frisco          | TX         |          0
(10 rows)
```

다음 예에서는 VENUE\$1SALES와 TOP\$1VENUES라는 두 테이블을 생성하는 WITH 절을 보여줍니다. 두 번째 WITH 절 테이블은 첫 번째 WITH 절 테이블에서 선택합니다. 다음에는, 기본 쿼리 블록의 WHERE 절이 TOP\$1VENUES 테이블을 포함하는 하위 쿼리를 포함합니다.

```
with venue_sales as
(select venuename, venuecity, sum(pricepaid) as venuename_sales
from sales, venue, event
where venue.venueid=event.venueid and event.eventid=sales.eventid
group by venuename, venuecity),

top_venues as
(select venuename
from venue_sales
where venuename_sales > 800000)

select venuename, venuecity, venuestate,
sum(qtysold) as venue_qty,
sum(pricepaid) as venue_sales
from sales, venue, event
where venue.venueid=event.venueid and event.eventid=sales.eventid
and venuename in(select venuename from top_venues)
group by venuename, venuecity, venuestate
order by venuename;
```

```
        venuename       |   venuecity   | venuestate | venue_qty | venue_sales
------------------------+---------------+------------+-----------+-------------
August Wilson Theatre   | New York City | NY         |      3187 |  1032156.00
Biltmore Theatre        | New York City | NY         |      2629 |   828981.00
Charles Playhouse       | Boston        | MA         |      2502 |   857031.00
Ethel Barrymore Theatre | New York City | NY         |      2828 |   891172.00
Eugene O'Neill Theatre  | New York City | NY         |      2488 |   828950.00
Greek Theatre           | Los Angeles   | CA         |      2445 |   838918.00
Helen Hayes Theatre     | New York City | NY         |      2948 |   978765.00
Hilton Theatre          | New York City | NY         |      2999 |   885686.00
Imperial Theatre        | New York City | NY         |      2702 |   877993.00
Lunt-Fontanne Theatre   | New York City | NY         |      3326 |  1115182.00
Majestic Theatre        | New York City | NY         |      2549 |   894275.00
Nederlander Theatre     | New York City | NY         |      2934 |   936312.00
Pasadena Playhouse      | Pasadena      | CA         |      2739 |   820435.00
Winter Garden Theatre   | New York City | NY         |      2838 |   939257.00
(14 rows)
```

다음 두 예에서는 WITH 절 하위 쿼리를 기반으로 테이블 참조의 범위에 대한 규칙을 보여줍니다. 첫 번째 쿼리가 실행되지만 두 번째 쿼리는 예상된 오류가 발생하며 실패합니다. 첫 번째 쿼리는 기본 쿼리의 SELECT 목록 내에 WITH 절 하위 쿼리가 있습니다. WITH 절(HOLIDAYS)에 의해 정의되는 테이블은 SELECT 목록에 있는 하위 쿼리의 FROM 절에 참조됩니다.

```
select caldate, sum(pricepaid) as daysales,
(with holidays as (select * from date where holiday ='t')
select sum(pricepaid)
from sales join holidays on sales.dateid=holidays.dateid
where caldate='2008-12-25') as dec25sales
from sales join date on sales.dateid=date.dateid
where caldate in('2008-12-25','2008-12-31')
group by caldate
order by caldate;

caldate   | daysales | dec25sales
-----------+----------+------------
2008-12-25 | 70402.00 |   70402.00
2008-12-31 | 12678.00 |   70402.00
(2 rows)
```

기본 쿼리뿐 아니라 SELECT 목록 하위 쿼리에서 HOLIDAYS 테이블 참조를 시도하므로 두 번째 쿼리는 실패합니다. 기본 쿼리 참조는 범위를 벗어나는 주제입니다.

```
select caldate, sum(pricepaid) as daysales,
(with holidays as (select * from date where holiday ='t')
select sum(pricepaid)
from sales join holidays on sales.dateid=holidays.dateid
where caldate='2008-12-25') as dec25sales
from sales join holidays on sales.dateid=holidays.dateid
where caldate in('2008-12-25','2008-12-31')
group by caldate
order by caldate;

ERROR:  relation "holidays" does not exist
```