动态列选择SQL

时间:2013-10-15 16:24:08

标签: sql sql-server ssis dynamic-programming

我的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中的规范将数字(或者是)FTIV_Returns.TR或.Net乘以DIM_Benchmark.weight。 DIM_Benchmark.Type_Return中的变量与FACT_Returns中的列标题相同。

与往常一样,任何帮助都非常感谢!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

请记住,我确保只考虑TR的{​​{1}}和Net值。如果您在该列中只有SUMTR,那么您可以将案例更改为:

Net

哪个会稍快一点。

输出:

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

小提琴here

答案 2 :(得分: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