2014-11-15 3 views
2

내가 이렇게 보이는 쿼리를 가지고 :가장 효과적인 방법

SELECT COUNT(DISTINCT A) as a_distinct, 
     COUNT(DISTINCT B) as b_distinct, 
     COUNT(DISTINCT A)/COUNT(DISTINCT B) as a_b_ratio 
FROM 
     sometable_ab 

우리는 집계 함수를 두 번 그들이 계산 된 경우에도 실행으로 이것은 매우 비효율적 보이는 볼 수 있듯이 . 나는 문제에 대한 하나의 해결책을 두 개의 쿼리로 나누는 것만 생각할 수 있습니다. 그게 유일한 해결책 일까? 아니면 할 수있는 더 효율적인 솔루션입니다. 나는 PostgreSQL을 주로 사용하는 Redshift DB를 사용하고 있지만, 효율적으로 수행 할 수있는 DB의 방식을 생각할 수 없기 때문에 심지어 MYSQL의 솔루션도 사용할 수 있습니다.

SELECT a_distinct, b_distinct, a_distinct/b_distinct as a_b_ratio 
FROM (SELECT COUNT(DISTINCT A) as a_distinct, 
      COUNT(DISTINCT B) as b_distinct 
     FROM sometable_ab 
    ) ab 

대부분의 집계 함수의 경우,이 관련성이없는,하지만 count(distinct)는 성능 돼지가 될 수 있습니다 당신이 성능에 미치는 영향에 대해 걱정하는 경우

+5

* "... 집계 함수가 두 번 실행됩니다."* 어떻게 알았습니까? –

+0

@ MikeSherrill'CatRecall 어떻게 실행되는지 어떻게 알 수 있습니까? 설명이 계획을 혼동하게 만듭니다. – Sohaib

+0

[EXPLAIN (ANALYZE, TIMING OFF)] (http://www.postgresql.org/docs/current/interactive/sql-explain.html)을 사용하여 큰 테이블에서 모든 쿼리 변형을 실행하고 찾아내는 데 가장 좋은 실행 시간. 쿼리 계획, 실행 시간 만 필요하지 않습니다. –

답변

3

, 그냥 하위 쿼리를 사용합니다.

이것은 ANSI 표준 SQL이며 사용자가 언급 한 모든 데이터베이스에서 작동해야합니다.

+1

하지만 다시 이것은 일종의 두 가지 질문입니다. 좀 더 미묘한 것을 생각할 수 있었습니까? – Sohaib

+1

@Sohaib. . . 이 쿼리는 하위 쿼리를 사용하는 하나의 쿼리입니다. 그것은 * 두 가지 쿼리가 아닙니다. Postgres와 (아마도 Redshift) 하위 쿼리를 사용하면 아무런 차이가 없습니다. 서브 쿼리를 구현하는 MySQL에서도 두 열과 두 행을 가진 중간 결과에 대해 이야기하고 있습니다. 완전히 무시할 수 있습니다. –

+0

@GordonLinoff : PostgreSQL 9.3에 대한 빠른 테스트를 로컬에서 수행했습니다. 서브 쿼리 스캔을 제외하고 두 실행 계획은 동일합니다. –

0

하위 쿼리를 사용하면 모든 RDBMS에 대해 하나의 쿼리가 계속 계산됩니다. 더 중요한 것은 count()은 NULL을 반환하지 않지만 행이 없으면 (또는 모든 행의 주어진 표현식에 대해 null이 아닌 값이 없음) 0을 반환합니다. 이 경우 을 0으로 나누면 0이됩니다. 예외. NULLIF (표준 SQL)으로 수정하십시오. 이 경우 NULL이됩니다.

SELECT *, a_distinct/NULLIF(b_distinct, 0) AS a_b_ratio 
FROM (
    SELECT count(DISTINCT a) AS a_distinct 
     , count(DISTINCT b) AS b_distinct 
    FROM sometable_ab 
    ) sub;
관련 문제