2017-05-11 2 views
1

CASE 식을 기반으로 집계를 수행하는보기를 만들었습니다. 뷰가 기반으로하는 트랜잭션 테이블에는 약 9 억 개의 행이 있습니다. 날짜와 제품 코드를 포함한 여러 기준을 토대로 가치를 집계해야합니다. 필터없이 집계를 수행 할 때 데이터를 한 번만 전체 검사해야 할 필요가 있으므로 case 문을 사용하면 각 조건에 대한 쿼리를 실행하지 않고 단지 한 번의 검사 만 수행 할 수 있습니다.집계 사례 구문 집계 SQL Server

내가 알기로는 너무 많은 집계 사례 문을 사용하는 것이 실제로 속도가 느려진다는 것입니다.

이 사례를 집계 아닌 다른 방법이있다 : 여기

는 명확성을 위해

SELECT [ContactID] AS [ContactID], 
     COUNT(DISTINCT CASE 
          WHEN [Category] = 'Dog Food' 
           AND [TransactionDate] 
           BETWEEN DATEADD(MONTH, -12, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) 
           THEN [TransactionDate] 
          ELSE NULL 
         END 
      )  AS [Dog_FoodTx12mth], 
     COUNT(DISTINCT CASE 
          WHEN [Category] = 'Cat Food' 
           AND [Lifestage] LIKE 'Kitten%' 
           AND [TransactionDate] 
           BETWEEN DATEADD(MONTH, -3, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) 
           THEN [TransactionDate] 
          ELSE NULL 
         END 
      )  AS [Cat_FoodKittenTx3mth] 
FROM [dbo].[GI_TransactionLineProductContact] 
GROUP BY [ContactID]; 

편집 질문 (실제 쿼리에서 아마 50 열이있을 것입니다) 단 2 열 내 쿼리의 예입니다 어쨌든 적어도 한 번 이상 테이블을 완전히 읽어야 할 것임을 명심하십시오. 내 주요 문제는 다른 CASE 표현식에 대한 모든 중첩 루프라고 생각합니다. 각각의 새로운 case 표현식은 많은 비용을 추가하는 것으로 보입니다. 2 개의 CASE 표현식과 50 개의 CASE 표현식을 가진 동일한 기준에 대한 쿼리의 예상 실행 계획을 수행하면 첫 번째 쿼리는 20 %의 비용을 나타내고 두 번째 쿼리는 80 %의 배치 비용을 보여줍니다.

그래서이 디자인이 가장 효율적이지 않고 사용할 수있는 잠재적 인 대체 방법을 찾고 있다고 생각합니다.

감사합니다.

+0

'count (distinct) '를 제거 할 수 있습니까? –

+0

또한'DATEADD (DAY, DATEDIFF (DAY, 0, GETDATE()), 0)'을'GETDATE()'로 대체 할 수 없습니까? 당신이 그걸로 무엇을 하려는지 확실하지 않습니까? 또는'CAST (GETDATE() AS DATE)' – Tanner

+0

이 경우 뚜렷한 부분을 없앨 수는 없습니다. dateadd가 날짜에서 시간을 스트립하고 있습니다. 네, 캐스트 (GetDate()로 Date) 할 수 있지만 내 연구 datead 메서드가 더 효율적임을 보여 주었다. –

답변

0

우선 질문이 잘못되었습니다. 잘못된 출력을 내 보냅니다.

두 번째 용도는 DISTINCT가 명확하지 않습니다.

는 오른쪽 출력을 받고 있지 않은 경우 다음

SELECT [ContactID] AS [ContactID], 
     sum(CASE 
          WHEN [Category] = 'Dog Food' 
           AND [TransactionDate] 
           BETWEEN DATEADD(MONTH, -12, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) 
           THEN 1 
          ELSE 0 
         END 
      )  AS [Dog_FoodTx12mth], 
     SUM(CASE 
          WHEN [Category] = 'Cat Food' 
           AND [Lifestage] LIKE 'Kitten%' 
           AND [TransactionDate] 
           BETWEEN DATEADD(MONTH, -3, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0) 
           THEN 1 
          ELSE 0 
         END 
      )  AS [Cat_FoodKittenTx3mth] 
FROM [dbo].[GI_TransactionLineProductContact] 
GROUP BY [ContactID]; 

이 왜 쿼리가 잘못 될 수도 다시 DISTINCT 넣을 수 있습니다, 내 스크립트를 시도?

select count(*) from 
(
select 1 col 
union all 
select null 
)t4 

출력 반환 값은 2.desire output = 1.Am I wrong/correct?

경우는 HV 다음 CTE 필터

는 ContactID가 + 카테고리에 의해 그룹에 더 효율적입니다
+0

출력이 왜 잘못되었는지 구체적으로 설명 할 수 있습니까? 거래에서 구매 한 각 제품에 대해 거래 날짜가 여러 번 반환되므로 구분해야합니다.나는 그 기준을 충족시키는 고유 한 날짜 수를 세고 싶습니다. 각 행이 아닙니다. COUNT는 null을 계산하지 않으므로 기준이 충족되지 않는 곳에서 널 (null)을 리턴합니다. –

+0

@Bee_Riii, 내 대답을 확인하십시오 .BTW 출력이 잘못 되었습니까? – KumarHarsh

+0

답변에 기둥이 포함되어 있지 않습니다. 는 에서 SELECT COUNT (ExampleColumn를) T4 –

0

RN (카테고리별로 파티션, transactiondate에 의해 transactiondate 순서) 이상() 하나의 별개의 또는 ROW_NUMBER를 사용하여 기록을 중복 사용하여 DISTINCT 사용하기 + Lifestage + 필요한 TransactionDate의 간격 (예 : td_year, td_month, td_day) + 기준으로 필요한 다른 모든 필드. 그런 다음 표준 집계를 사용하고 마지막으로 임의의 기술 (WITH, 임시 테이블, 중첩 된 선택,보기 등)을 사용하여 외부 선택에서 ContactID로 해당 그룹을 선택합니다.