2013-06-07 2 views
1

는 다음 사항을 고려하십시오 : 10 개 개의 레코드의 총이있다여러 필드의 고유 값 조합 수 계산.

IF OBJECT_ID ('tempdb..#Customer') IS NOT NULL 
    DROP TABLE #Customer; 

CREATE TABLE #Customer 
(
    CustomerKey INT IDENTITY (1, 1) NOT NULL 
    ,CustomerNum INT NOT NULL 
    ,CustomerName VARCHAR (25) NOT NULL 
    ,Planet   VARCHAR (25) NOT NULL 
) 
GO 

INSERT INTO #Customer (CustomerNum, CustomerName, Planet) 
VALUES (1, 'Anakin Skywalker', 'Tatooine') 
     , (2, 'Yoda', 'Coruscant') 
     , (3, 'Obi-Wan Kenobi', 'Coruscant') 
     , (4, 'Luke Skywalker', 'Tatooine') 
     , (4, 'Luke Skywalker', 'Tatooine') 
     , (4, 'Luke Skywalker', 'Bespin') 
     , (4, 'Luke Skywalker', 'Bespin') 
     , (4, 'Luke Skywalker', 'Endor') 
     , (4, 'Luke Skywalker', 'Tatooine') 
     , (4, 'Luke Skywalker', 'Kashyyyk'); 

공지있다. 다음 두 쿼리 중 CustomerName과 PLanet의 고유 한 조합 목록을 얻을 수 있다는 것을 알고 있습니다.

SELECT DISTINCT CustomerName, Planet FROM #Customer; 

SELECT CustomerName, Planet FROM #Customer 
GROUP BY CustomerName, Planet; 

그러나 내가 원하는 것은 값 자체가 아니라 그 값의 개수를 얻는 간단한 방법입니다. 나는 타이핑하는 방법이 빠르며, 공연도하고 싶습니다. CTE, 임시 테이블, 테이블 변수 또는 하위 쿼리에 값을로드 한 다음 레코드를 계산할 수 있음을 알고 있습니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

+0

"빠른 입력"이 필요한 이유는 무엇입니까? 얼마나 자주 이러한 쿼리를 직접 작성하고 있습니까? 쿼리가 더 효율적인지 또는 쿼리가 "빠르게 입력되는"것이 더 중요한지 알려주실 수 있습니까? –

+1

[@ ypercube의 SQLFiddle] (http://sqlfiddle.com/#!6/d8deb/25)에 몇 가지 다른 유사 검색어를 추가했습니다. 당신은 그 (것)들을 시험해야하고 그 후에 * 당신은 당신의 타자를 치는 손가락에 성과 그리고/또는 긴장에 근거하여 당신이 가장 좋아하는 것을 결정할 수있다. –

+0

[SQL - 열의 고유 한 조합을 계산하는 방법] 가능한 복제본 (http://stackoverflow.com/questions/8519747/sql-how-to-count-unique-combination-of-columns) – Chronial

답변

6

이 2005 년에 작동합니다

SELECT COUNT(*) AS cnt 
FROM 
(SELECT 1 AS d 
    FROM Customer 
    GROUP BY Customername, Planet 
) AS t ; 

SQL-Fiddle에서 테스트.

Query Plan

, "다음, 하위 쿼리의 모든 고유 값을 얻을 계산"생각하는 가장 간단한 같은 동일한 계획을 yiields : (CustomerName, Planet)에 대한 인덱스는 (2012 버전) 쿼리 계획을 참조 사용될 것입니다 :

SELECT COUNT(*) AS cnt 
FROM 
 (SELECT DISTINCT Customername, Planet 
   FROM  Customer 
 ) AS t ; 

그리고 또 하나 (@Aaron 버트 랜드에 고맙습니다) 함수 ROW_NUMBER() 순위를 사용하여 (도는 2005 버전에서 효율적입니다 있는지 확실하지 않습니다,하지만 당신은 테스트 할 수 있습니다) :

SELECT COUNT(*) AS cnt 
FROM 
    (SELECT rn = ROW_NUMBER() 
      OVER (PARTITION BY CustomerName, Planet 
       ORDER BY CustomerName) 
    FROM Customer) AS x 
WHERE rn = 1 ; 
,

다른 방법으로도 작성할 수 있지만 (@Mikael Erksson에게는 서브 쿼리가 없어도 하나!) 효율적이지는 않습니다.

+0

업데이트 된 [SQL Fiddle]에서 고양이를 스킨으로 처리하는 두 가지 방법 (http://sqlfiddle.com/#!6/d8deb/49). –

+0

@ AndriyM Thanx Andriy! –

2

하위 쿼리/CTE 방법은 "올바른"방법입니다.

빠른 (성능 입력의 측면에서 반드시 그런 것은 아니지만) 더러운 방법은 다음과 같습니다

select count(distinct customername+'###'+Planet) 
from #Customer; 

'###'은 우발적 충돌하지 않도록 값을 분리하는 것입니다.

+0

끔찍한 성능 . 그리고 여러분은'#'이 자연스럽게 데이터에 나타날 수 없다는 것을 확신해야합니다. –

+0

@AaronBertrand. . . OP는 구체적으로 CTE/하위 쿼리 등을 사용하지 말라고 말합니다. "CTE, 임시 테이블, 테이블 변수 또는 하위 쿼리에 값을로드 한 다음 레코드를 계산할 수 있습니다." 다른 방법을 생각해 볼 수 있습니까? –

+0

나는 그것을 깨닫는다. 내 의견은 OP를위한 것이 아닙니다 (단어가 아닌 "공연자"가 요구 사항 임). 당신의 대답은 사람들로 하여금 하위 쿼리와 동일하거나 또는 심지어 더 잘 수행 할 수 있다고 믿게하는 "빠르고 더러운 방법"을 말합니다. 하위 쿼리/CTE 방식보다 실제로 느릴 것이라는 면책 조항을 포함해야합니다.* 하위 쿼리/CTE를 사용하지 않는 것은 어쨌든 인공적인 것이라고 생각합니다. * –