2013-10-15 2 views
3

SQL 데이터베이스에 다음 표가 있습니다. 저장 프로 시저의동적 열 선택 SQL

DIM_BENCHMARK: 
Fund_sk | Num_Bench | Bench | Weight | Type_Return 
    1   2  XXX  0.9  TR 
    1   2  YYY  0.1  Net 
    2   3  XXX  0.45  TR 
    2   3  YYY  0.45  TR 
    2   3  ZZZ  0.10  Net 

FACT_Returns: 
Date | Bench | TR | Net 
10/10 XXX 0.010 0.005 
10/10 YYY 0.012 0.008 
10/10 ZZZ 0.006 0.012 

원하는 출력은 :

FACT_Result: 
Date | Fund_SK | Num_Bench |  Bench_Returns 
10/10  1   2   (eg. 0.9*TR of XXX) + (0.1*Net Return of YYY) 
10/10  2   3   (eg. 0.45*TR of XXX) + (0.45*TR of YYY) + (0.10*Net of ZZZ) 

테이블 위 내 입력 데이터의 포맷 내 원하는 출력을 나타낸다. 필자는 여전히 SQL에 익숙하지 않은데,이 동적 인 SQL 질의는 내 지식의 깊이를 넘어서고 있습니다.

DIM_Benchmark.Type_Return의 사양에 따라 FACT_Returns.TR 또는 .Net을 DIM_Benchmark.weight로 곱하고 싶습니다. DIM_Benchmark.Type_Return의 변수는 FACT_Returns의 열 머리글과 같습니다.

언제나처럼 어떤 도움도 대단히 감사하겠습니다!

+0

동일한 Fund_sk 및 num_bench를 가진 행이 여러 개 있지만 벤치 열은 각 fund_sk마다 고유 할 가능성이 큽니다. – Patrick

+1

귀하의 테이블은 DIM이며 FACT는 이것이 스타 스키마임을 암시하지만 그렇지 않습니다. 사실과 차원간에 n : n 조인을해서는 안되기 때문에이 데이터웨어 하우스가 제대로 설계되지 않았다는 것을 알아야합니다. –

+0

귀하의 의견에 따라 ETL에 액세스 할 수 있으며 직접 테이블 형식을 변경할 수있었습니다. 의견을 보내 주셔서 감사합니다. 나는 미쳤다. ... – Patrick

답변

3

주요 문제는 사실 테이블입니다. 제대로 정규화되지 않았습니다. 각 값에 대해 하나의 행을 가져야합니다.

아래 SQL의 unpivot은 데이터를 정상화합니다.

select 
    [date], fund_sk,Num_Bench, sum(weight * val)  
from 
(
    select * 
    from fact_returns 
    unpivot (val for type in (tr, net)) u 
) f 
    inner join dim_benchmark b 
     on f.bench = b.Bench 
     and f.type = b.Type_Return 
group by [date], fund_sk, Num_Bench 
+0

고마워. 테이블 unpivot에 대한 제안에 따라 ETL에 액세스 할 수 있었으며 원본 테이블을 포맷 할 수있었습니다. – Patrick

0

사례를 사용하여 각 행을 계산하면 합계가 적절하게 계산됩니다.

select 
    _BenchResults.date 
    ,_BenchResults.Fund_SK 
    ,_BenchResults.Num_Bench 
    ,sum(_BenchResults.benchReturns) as benchReturns 
from (
    select 
     FACT_Result.date 
     ,DIM_BENCHMARK.Fund_SK 
     ,DIM_BENCHMARK.Num_Bench 
     ,case when DIM_BENCHMARK.Type_Return = 'TR' then 
      DIM_BENCHMARK.Weight * FACT_Result.tr 
     when DIM_BENCHMARK.Type_Return = 'Net' then 
      DIM_BENCHMARK.Weight * FACT_Result.net 
     else 
      0 
     end as benchReturns 
    from DIM_BENCHMARK 
    join FACT_Result 
     on FACT_Result.bench = DIM_BENCHMARK.bench 
) _BenchResults 
group by 
    _BenchResults.date 
    ,_BenchResults.Fund_SK 
    ,_BenchResults.Num_Bench 
2

이 문제를 해결해야하며, 또한 어떤 DBMS에서 작동합니다 :

곰 염두에 나는 확실히에만 TRNet 값이 SUM에 대한 고려 만들고있어
SELECT fr.date, db.fund_sk, db.num_bench, sum(db.weight * 
    CASE db.type_return 
    WHEN 'TR' THEN fr.tr 
    WHEN 'Net' THEN fr.net 
    ELSE 0 
    END) Bench_Returns 
FROM dim_benchmark db 
JOIN fact_returns fr ON db.bench = fr.bench 
GROUP BY fr.date, db.fund_sk, db.num_bench 

. 약간 빠른 실행됩니다

CASE db.type_return 
    WHEN 'TR' THEN fr.tr 
    ELSE fr.net 
    END 

: 당신은 단지 해당 열에 TRNet이있는 경우 다음의 정보는 다음의 제품에 사건을 변경할 수 있습니다.

출력 :

| DATE | FUND_SK | NUM_BENCH | BENCH_RETURNS | 
|-------|---------|-----------|---------------| 
| 10/10 |  1 |   2 |  0.0098 | 
| 10/10 |  2 |   3 |  0.0111 | 

바이올린 here.