2014-02-28 3 views
1

같은 WHERE 절을 공유하는 여러 SQL 쿼리를 수행하고 싶습니다. 내 쿼리에는 모두 여러 그룹의 항목 수를 계산하는 쿼리가 포함됩니다. 지금은 각 쿼리를 개별적으로 실행하고 있는데 아마도 WHERE 필터가 여러 번 적용될 수 있습니다. 이것은 낭비가 보인다. WHERE 절이 한 번만 호출되도록 쿼리를 결합하는 방법이 있습니까? 보다 일반적으로 아래의 쿼리를보다 효율적으로 만들 수있는 방법이 있습니까?동일한 WHERE 절을 사용하여 여러 SQL 쿼리를 효율적으로 실행하는 방법

특히 공자의 테이블이 있다고 가정 해 보겠습니다. 내가 좋아하는 것

PublicFigures

last_name | occupation | age | state | has_dogs 
--------------------------------------------------- 
Stewart | comedian  | 51 | NY | true 
Colbert | comedian  | 49 | NJ | false 
Obama  | president | 52 | DC | true 
Romney | consultant | 66 | CA | true 
(etc..) 

테이블에서 두 가지 유형의 정보를 추출합니다. 첫째, 각 직업마다 얼마나 자주 각 성이 표시되는지, 두 번째로, 국가 별 개 소유에 대한 데이터를 원합니다. 두 경우 모두 55 세 미만의 공영 인물에만 관심이 있습니다. 따라서 두 쿼리 모두 동일한 WHERE 절을 사용합니다. 방법이 있나요

SELECT state, has_dogs, COUNT(*) as count WHERE age < 55 FROM "PublicFigures" GROUP BY state, has_dogs 


state | has_dogs | count 
--------------------------------------------------- 
NY | true  | 1 
NY | false | 0 
NJ | true  | 0 
NJ | false | 0 
DC | true  | 1 
DC | false | 1 

:

이름과 직업에 대한 첫 번째 쿼리는이

SELECT last_name, occupation, COUNT(*) as count WHERE age < 55 FROM "PublicFigures" GROUP BY last_name, occupation 

처럼 보이는 두 번째 질의는 이것이다이

last_name | occupation | count 
--------------------------------- 
Stewart | comedian  | 1 
Stewart | president | 0 
Colbert | comedian  | 1 
Colbert | president | 0 
Obama  | comedian  | 0 
Obama  | president | 1 

제공 이러한 결과를 얻으려면이 두 개의 쿼리보다 더 효율적입니다. 두 쿼리를 어떻게 든 결합 할 수 있습니까?

실생활에서는 물론 테이블이 커지고 쿼리가 많아지고 필터링 조건이 더 복잡해졌습니다. 나는 더 똑똑한 SQL에서 절약 할 수있는 비용 절감 효과가 상당하다고 생각합니다. 가능한 경우 Rails3에 친숙한 ActiveRecord의 솔루션에 특히 감사하겠습니다.

아이디어가 있으십니까?

+0

을 반복적으로 쿼리하십시오. –

+0

허. 승인. 그것은 사실 일 수 있습니다. 내가 예상했던 대답이 아니라, 당신이 옳을 수도 있습니다! 감사. –

+0

대안으로는 창 함수를 통한 계산, 즉 그룹화 대신에 over (partition by ..)를 사용할 수 있지만 Sam D와 가능한 경우 매우 복잡한 쿼리를 피하는 데 동의합니다. – Jayvee

답변

1

여기는 색인으로 놀라운 일입니다. 인덱스 생성과 결합 할 수있는 또 다른 접근법은 한 번 필터를 여러 번 선택하는 것입니다. 다행히도 이것은 당신에게 뭔가를 사 줄 것이지만 올바른 색인 만 있으면 충분할 것입니다.

CREATE INDEX pidx_public_figures_age ON public_figures (age) 
WHERE age < 55; 
--Try temp table with the index and also try just the new index and see if all your queries now run as fast as you would hope. 
CREATE TEMPORARY TABLE temp_public_figures AS 
SELECT last_name, occupation ,age, state, has_dogs 
FROM films WHERE age < 55; 

이제 실제 테이블에 대해 또는 임시 테이블 접근 방식 중 하나를 쿼리하여 N 번호를 실행하고 방금 빨리 각 쿼리를 만들 수 있다면 사용 사례

SELECT last_name, occupation, COUNT(*) as count 
FROM temp_public_figures 
GROUP BY last_name, occupation; 

SELECT state, has_dogs, COUNT(*) as count 
FROM temp_public_figures 
GROUP BY state, has_dogs; 
+0

그들은 불가사의하게 작동하는 올바른 데이터 배포에서 부분 색인을 특별히 주목하십시오. http://www.postgresql.org/docs/9.3/static/indexes-partial.html – Kuberchaun

2

에서 더 좋은 성능을 확인할 예를 들어, 최선의 방법이 될 수있는 색인을 작성하여 독립 실행 형 기반을 구축하십시오. 그렇지 않다면 임시 테이블을 만든 다음 원본 대신 반복적으로 쿼리하십시오. 두 개의 비교적 간단한 쿼리가 하나의 매우 복잡한 쿼리보다 낫다면

create temporary table young_figures as 
    select * from public_figures where age < 55; 
관련 문제