查询一系列数据时的Oracle SQL

时间:2016-09-02 21:47:36

标签: function plsql oracle11g

我有一个表,对于ID,将在多个存储桶字段中包含数据。我想要一个函数来提取一个桶的总和,但函数参数将包括开始和结束桶字段。

所以,如果我有这样的表:

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

如果我发送ID和参数Bucket0,Bucket0,它将仅返回Bucket0字段中的值:5.00

如果我发送了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 个答案:

答案 0 :(得分:1)

如果您的表格已经标准化会更好,例如:

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

此外,存储桶最好具有易于在范围内进行比较的名称,因此bucket030按照正常的字母顺序介于bucket000bucket120之间,但事实并非如此如果你遗漏了填充的零。

如果无法进行上述规范化,则使用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

使用参数变量执行此操作时,请确保这些参数也具有填充的零。

例如,您可以确保 parameter1

的内容如下所示
if parameter1 like 'bucket%' then
    parameter1 := 'bucket' || lpad(+substr(parameter1, 7), 3, '0');
end if;

...等