2016-09-02 12 views
0

IDのためにいくつかのバケットフィールドにデータを持つテーブルがあります。バケットの合計を取り出す関数が必要ですが、関数のパラメータには開始バケットフィールドと終了バケットフィールドが含まれます。データの範囲を照会するときのOracle SQL

だから、私はこのようなテーブルがあった場合:5.00

:私はIDとパラメータのbucket0、のbucket0に送信する場合

ID Bucket0 Bucket30 Bucket60 Bucket90 Bucket120 
10  5.00 12.00  10.00  0.0  8.00 

、それはのbucket0フィールドの値のみを返しますIDとパラメータBucket30、Bucket120を送信すると、30から120または(12 + 10 + 0 + 8)30.00のバケットの合計が返されます。

はこれに巨大な醜い

if parameter1=bucket0 and parameter2=bucket0 
    then select bucket0 
else if parameter1=bucket0 and parameter2=bucket1 
    then select bucket0 + bucket1 
else if parameter1=bucket0 and parameter2=bucket2 
    then select bucket0 + bucket1 + bucket2 

とよりも、この他を書くためのよりよい方法はありますか?

テーブルは既に存在しているので、私はそれ以上のコントロールはありません。私は関数のために自分のパラメータを作ることができますが、私は欲しいです。私はバケツのセットが必要な場合、途中のものはスキップされないので、開始と終了のバケットを指定すると動作すると言うことはできます。私はすべてのバケツが必要なカンマ区切りの文字列を1つ持つことができました。

+1

あなたのデータベース設計が欲しいときに素敵な方法はあまり効果的ではありません。バケット列は別々の列であってはなりません。代わりに、 'bucket'と' bucket_id'という2つのカラムがあり、より多くの行を持っているはずです。 – trincot

+0

@trincotそうかもしれないが、私が言ったように、私はそれを支配していない。 – thursdaysgeek

答えて

1

あなたのテーブルが正規化されていた場合、それはこのように、もっと良かったはず:

id | bucket | value 
---+-----------+------ 
10 | bucket000 | 5 
10 | bucket030 | 12 
10 | bucket060 | 10 
10 | bucket090 | 0 
10 | bucket120 | 8 

bucket030bucket000bucket120の間で来るように。また、バケットが良く、範囲で比較しやすい名前を持つ必要があります通常のアルファベット順に並べ替えられます。パディングされたゼロを除外した場合はそうではありません。

上記の正規化が不可能な場合は、上記の描かれた構造にあなたの現在のテーブルを回すためにunpivot句を使用します。これらのパラメータは、パディングを持っていることを確認し、あなたはパラメータ変数でこれを行うと

select id, sum(value) 
from (
     select * 
     from mytable 
     unpivot (value for bucket_id in (bucket0 as 'bucket000', 
             bucket30 as 'bucket030', 
             bucket60 as 'bucket060', 
             bucket90 as 'bucket090', 
             bucket120 as 'bucket120')) 
    ) normalised 
where bucket_id between 'bucket000' and 'bucket060' 
group by id 

ゼロも同様です。

パラメーター1ために、次のようにあなたは、インスタンスのためのことを確認できます。

if parameter1 like 'bucket%' then 
    parameter1 := 'bucket' || lpad(+substr(parameter1, 7), 3, '0'); 
end if; 

...など。

関連する問題