2013-08-27 5 views
1

실험, 기능 및 feature_values가 있습니다. 기능은 다른 실험에서 가치가 있습니다. 그래서 같은 것을 가지고 말할 수PostgreSQL 결과를 평평하게하는 방법

Experiments: 
experiment_id, experiment_name 

Features: 
feature_id, feature_name 

Feature_values: 
experiment_id, feature_id, value 

을, 나는 세 가지 실험 (EXP1, EXP2, exp3)와 세 가지 기능을 가지고 (feat1, feat2, feat3). 나는처럼 보이는 SQL-결과를 가지고 싶다 :

feature_name | exp1 | exp2 | exp3 
-------------+------+------+----- 
feat1  | 100 | 150 | 110 
feat2  | 200 | 250 | 210 
feat3  | 300 | 350 | 310 

내가 어떻게 할 수 있습니까? 또한 하나의 기능이 하나의 실험에서 값을 가지지 않을 수도 있습니다.

feature_name | exp1 | exp2 | exp3 
-------------+------+------+----- 
feat1  | 100 | 150 | 110 
feat2  | 200 |  | 210 
feat3  |  | 350 | 310 

SQL-Query는 성능이 우수해야합니다. 나중에 feature_values ​​테이블에 수천만 개의 항목이있을 수 있습니다. 데이터를 처리하는 더 좋은 방법이 있습니까?

+0

@ 7alhashmi : 예, 예. 100은 feature_values ​​테이블에서 가져옵니다. – Bjoernsen

답변

2

여기서 feature_id, experiment_idFeature_values의 고유 키입니다.

select 
    F.feature_name, 
    max(case when E.experiment_name = 'exp1' then FV.value end) as exp1, 
    max(case when E.experiment_name = 'exp2' then FV.value end) as exp2, 
    max(case when E.experiment_name = 'exp3' then FV.value end) as exp3 
from Features as F 
    left outer join Feature_values as FV on FV.feature_id = F.feature_id 
    left outer join Experiments as E on E.experiment_id = FV.experiment_id 
group by F.feature_name 
order by F.feature_name 

sql fiddle demo

당신에게 이렇게하는

표준 SQL 방법은 n이 같은

select 
    F.feature_name, 
    FV1.value as exp1, 
    FV2.value as exp2, 
    FV3.value as exp3 
from Features as F 
    left outer join Feature_values as FV1 on FV1.feature_id = F.feature_id and FV1.experiment_id = 1 
    left outer join Feature_values as FV2 on FV2.feature_id = F.feature_id and FV2.experiment_id = 2 
    left outer join Feature_values as FV3 on FV3.feature_id = F.feature_id and FV3.experiment_id = 3 

또는 피벗 데이터 (총 max 실제로 집계되지 않은 아무것도)에 가입하는 것입니다 json (9.3 버전) 또는 hstore을 사용하여 모든 실험 값을 하나의 열로 가져올 수도 있습니다. umn.

+0

선택한 실험 및 기능이 사용자 요청에 따라 변경되므로 hstore를 사용할 수 없습니다. 예를 들어 값을 필터링 할 수도 있습니다. 300 그러나 대답은 훌륭합니다 :-) – Bjoernsen

+0

값을 걸러 내고 싶다면 - 두 번째 솔루션에서 '왼쪽 외부 조인 Feature_values를 FV on FV.feature_id = F.feature_id 및 FV.value와 같이 조인에 조건을 추가하기 만하면됩니다 > 300' –

1

테이블 집합을 단일 테이블로 표시하려고하기 때문에 약간의 어려움이 있습니다. 분명히 일부 변형과 일부 가정이 포함됩니다.

이 경우 다음

SELECT 
    feature_id, 
    SUM(CASE WHEN experiment_id = 1 THEN value ELSE 0 END) AS Exp1Total, 
    SUM(CASE WHEN experiment_id = 2 THEN value ELSE 0 END) AS Exp2Total, 
    SUM(CASE WHEN experiment_id = 3 THEN value ELSE 0 END) AS Exp3Total, 
FROM 
    Feature_values 
GROUP BY 
    feature_id 
ORDER BY 
    feature_id 

같은 것을 할 수있는, 당신은 단지 3 실험과 단지 세 가지 기능이 있다는 것을 사전에 알고 있다고 가정하면, 테이블은 실험과의 ID가 포함됩니다 기능을 제공합니다. 이름을 얻으려면 기능 표와 실험 표에 가입해야합니다. 나는 가장 어려운 부분이 사건 논리라고 생각하기 때문에 이것을 생략했다.

+0

고맙습니다. 한 가지는 값이 누락되면 0이 아닙니다. 0은 값이됩니다. 나는 그것을 'null'로 바꿨다. – Bjoernsen

+0

환영합니다.하지만 null을 사용하면 SUM (1, null) == null 이래로 문제가 발생할 수 있습니다. – PhilDin

4

이것은 일반적인 요청입니다. 피벗 또는 크로스 탭 쿼리라고합니다. PostgreSQL에는 내장 된 구문이 없지만 the crosstab function from the tablefunc module to do what you want을 사용할 수 있습니다.

자세한 내용은 [postgresql] [pivot] 또는 [postgresql] [crosstab]에 대한 스택 오버플로 검색을 참조하십시오.

일부 관계형 데이터베이스 시스템은 기본 제공 쿼리로이를 수행하는 좋은 방법을 제공하지만 PostgreSQL은 그렇지 않습니다.

+0

크로스 탭에 대한 +1 링크에 대해 읽어야합니다. n 조인을하는 것이 함수 일 뿐이라고 생각해? –

+0

이것은 매우 유망한 것으로 들립니다. 고맙습니다. – Bjoernsen

+0

@RomanPekar 꽤 많이; 이것은 원하는 SQL을 동적으로 빌드하는 도구입니다. PostgreSQL은 알 수없는 유형의 결과 집합을 제대로 처리 할 수 ​​없다는 점에서 다소 제한적입니다. –

관련 문제