간단하게 유지하고 쿼리에서 여러 CTE를 수행하는 방법


156

이 간단한 T-SQL 쿼리가 있는데 테이블에서 많은 열을 내보내고 다른 관련 테이블의 정보를 조인합니다 .

내 데이터 모델은 간단합니다. 참가자들과 함께 예정된 행사가 있습니다. 각 이벤트에 참여하는 참가자 수를 알아야합니다.

이에 대한 나의 해결책은 예정된 이벤트를 그룹화하고 참가자 수를 계산하는 CTE를 추가하는 것입니다.

이를 통해 예정된 이벤트마다 해당 정보에 참여할 수 있습니다. 쿼리를 단순하게 유지하십시오.

그러나 쿼리를 단순하게 유지하고 싶습니다. 나중에 간단한 쿼리 중에 추가 임시 결과에 액세스 할 수 있어야하는 경우 어떻게해야합니까?

CTE를 여러 개 가질 수는 있지만 실제로는 불가능합니다. 내 옵션은 무엇입니까?

애플리케이션 데이터 계층에서 뷰를 수행하지 않고 작업을 수행하지 않았습니다. SQL 쿼리를 격리하는 것을 선호합니다.

답변:


297

CTE하나의 쿼리에 여러 개의을 가질 수 있으며 다음 을 재사용 할 수 있습니다 CTE.

WITH    cte1 AS
        (
        SELECT  1 AS id
        ),
        cte2 AS
        (
        SELECT  2 AS id
        )
SELECT  *
FROM    cte1
UNION ALL
SELECT  *
FROM    cte2
UNION ALL
SELECT  *
FROM    cte1

단, 그 SQL Server재평가 할 수 있습니다 CTE당신은 같은 값을 사용하는 그렇다면,이 액세스 될 때마다 RAND(), NEWID()등, 그들 사이에 변경 될 수 있습니다 CTE전화.


3
그렇게 간단했습니다. MSDN 설명서는이 문제와 관련하여 약간 애매했지만 결정적인 것을 찾을 수 없었습니다. 대단히 감사합니다!
John Leidegren

1
그것은에서 문서화 WITH common_table_expression (Transact-SQL)를 . 이은 (의 특별한주의 걸릴 구문 섹션에 볼 수 [ ,...n ]있는을 [ WITH <common_table_expression> [ ,...n ] ]명시 적으로이 부른다 ", 단일 쿼리에서 여러 CTE 정의 사용"을 참조하십시오. 예 C를,. 슬프게도,이 예제는 SQL 2008의 설명서에 제공되지 않습니다 이전 (예 : OP가 질문을 게시 할 때 제공되지 않은 예)
Brian

나는 이것에 대한 두 배의 레코드를 얻는다 : /
Tom Stickel

@TomStickel는 마지막 전에 쿼리의 절반 만 사용합니다UNION ALL
Quassnoi

@Quassnoi 그렇습니다. 나는 의견을 쓴 후에 그것을했다. 왜 2 차 노동 조합이 존재하는지 잘 모르겠습니다.
Tom Stickel

90

단일 쿼리 식에서 여러 CTE를 가질 수 있습니다. 쉼표로 구분하면됩니다. 다음은 예입니다. 아래 예에는 두 개의 CTE가 있습니다. 하나는 이름이 지정 CategoryAndNumberOfProducts되고 두 번째는 이름이 지정 ProductsOverTenDollars됩니다.

WITH CategoryAndNumberOfProducts (CategoryID, CategoryName, NumberOfProducts) AS
(
   SELECT
      CategoryID,
      CategoryName,
      (SELECT COUNT(1) FROM Products p
       WHERE p.CategoryID = c.CategoryID) as NumberOfProducts
   FROM Categories c
),

ProductsOverTenDollars (ProductID, CategoryID, ProductName, UnitPrice) AS
(
   SELECT
      ProductID,
      CategoryID,
      ProductName,
      UnitPrice
   FROM Products p
   WHERE UnitPrice > 10.0
)

SELECT c.CategoryName, c.NumberOfProducts,
      p.ProductName, p.UnitPrice
FROM ProductsOverTenDollars p
   INNER JOIN CategoryAndNumberOfProducts c ON
      p.CategoryID = c.CategoryID
ORDER BY ProductName

5
@JohnLeidegren : 첫 번째 정답 후 2 분 이내에 정답을 올리면 적어도 내가 준 공감대가 필요합니다.
피터 마 제드
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.