2013-10-15 126 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中的規格乘以DIM_Benchmark.weight的FACT_Returns.TR或.Net數字。 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

謝謝。根據您的建議,我可以訪問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的工作:

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 

請記住,我要確保只有TRNet值被認爲是SUM。如果你只有TRNet在列,那麼你可以改變的情況下:

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

這將稍快運行。

輸出:

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

小提琴here