按日期组合输出行

时间:2014-08-01 10:46:08

标签: sql plsql oracle11g oracle-sqldeveloper

PL / SQL有以下问题..

我需要从表中检索各种参数的数据,在特定的时间段内,但在输出中我有重复的日期为我提供每列的输出,但没有将它们组合在一起。我可以借用你的天才来解决这个问题吗?

这是我的代码(部分内容,因为它重复了我需要提供的其他参数):

select /*+FULL(k)*/ k.date_n,

 SUM(decode(bucket_flag_n,
        '1',
        (DECODE(type_s,
                    'MOC',
                    decode(on_off_net_s, 'On net', duration_sum),
                    'MOC_4',
                    decode(on_off_net_s, 'On net', duration_sum),
                    'MOC CF_4',
                    decode(on_off_net_s, 'On net', duration_sum),0)))) test1,

 SUM(decode(bucket_flag_n, 
         '0',
         (DECODE(type_s, 
                     'MOC',
                     decode(on_off_net_s, 'Off net', duration_sum),
                     'MOC_4', 
                     decode(on_off_net_s, 'Off net', duration_sum), 
                     'MOC CF_4', 
                     decode(on_off_net_s, 'Off net', duration_sum),0)))) test2

  from (select /*+FULL(a)*/
         a.d_timestamp date_n,
         a.service_s type_s,
         a.country_s,
         a.on_off_net_s,
         a.bucket_flag_n,
         round(SUM(a.duration_n / 60)) duration_sum, --minutes rounded
         SUM(a.count_n) sms_count, -- sms count
         round(SUM(a.volume_n / 1024 / 1024)) volume_sum -- volume mb rounded

          from database a, database2 b

         where a.country_s = 'Country'
           and a.free_of_charge_flag_n = '1'
           and a.d_timestamp between b.date_from and b.date_to
         group by a.d_timestamp,
                  a.service_s,
                  a.country_s,
                  a.on_off_net_s,
                  a.bucket_flag_n) k

 group by k.date_n, bucket_flag_n
 order by 1

以下是我在输出中的内容:

http://imgur.com/z4DGdtO

提前谢谢!

2 个答案:

答案 0 :(得分:0)

您的group by条款是:

group by k.date_n, bucket_flag_n

如果您每个日期只需要一行,请将其更改为:

group by k.date_n

我还建议您学习现代join语法("永远不要在from子句中使用逗号")并将decode()替换为case 。但是,这些是语法约定,不会影响查询结果。

答案 1 :(得分:0)

这里发生了几件奇怪的事情 首先,你说:

  

这是我的代码(部分代码,因为它对其他代码重复相同   我需要提供的参数):

这意味着所有聚合的非分组列都包含DECODE(...) 'MOC''MOC_4''MOC CF_4' - 如果是这样,您实际上可以使这些列成为WHERE子句,实际上可以加快查询速度(假设service_s在查询中没有使用其他代码,以及相关索引)。

接下来就是,你正在使用一个包含上限(<=,在BETWEEN中找到),看似是一个时间戳。 This will give you wrong results - 通常,第二天的午夜被错误地包括在内,尽管还有其他可能性。在处理正,连续范围类型时,必须使用独占上限(<),否则会产生后果:这是表示数字的固有属性,与计算机或特定应用程序中的实现无关。 (我也发现这些名字有点差,尤其是d_timestamp并没有真正告诉我它代表什么的内容)

数学和四舍五入问题:
假设duration_ncount_nvolumn_n(... _n代表什么?为什么后缀?)是INTEGER类型,{{1}这是不必要的,因为所有执行的数学运算都是基于整数的,并且首先返回非小数量。添加的可交换属性可能被利用 - 您可以将ROUND(...)重写为SUM(a.duration_n / 60)(性能增益,如果有的话,会很低) - 但是如果给定的列是SUM(a.duration_n) / 60类型你会得到不同的结果(这是正确的取决于你 - 实际上,考虑到计算机的限制,它会给出不同的答案,无论类型是什么,但最明显的是积分型)。


鉴于一些上述假设(即所有聚合列具有相同的INTEGER,我们可以稍微简化查询:

DECODE(..)

...添加剩余的聚合列留给读者练习 几点注意事项:如果SELECT A.d_timestamp AS date_n, SUM(CASE WHEN A.bucket_flag_n = '1' AND A.on_off_net_s = 'On net' THEN A.duration_n END) / 60 AS test1, SUM(CASE WHEN A.bucket_flag_n = '0' AND A.on_off_net_s = 'Off net' THEN A.duration_n END) / 60 AS test2 FROM Database A JOIN Database2 B ON A.d_timestamp >= B.date_from AND A.d_timestamp < B.date_to WHERE A.country_s = 'Country' AND A.free_of_charge_flag_n = '1' AND A.service_s IN ('MOC', 'MOC_4', 'MOC CF_4') AND ((bucket_flag_n = '1' AND on_off_net_s = 'On net') OR (bucket_flag_n = '0' AND on_off_net_s = 'Off net')) GROUP BY A.d_timestamp ORDER BY A.d_timestamp bucket_flag_n之间的关系如所有情况中所示,您实际上可以从on_off_net_s子句中删除条件。如果你还有其他的东西,你可能不得不反对。我也怀疑通过声称是时间戳的事物进行分组的有用性,因为这些通常对于聚合中的有用组来说分辨率太高(即 - 每个值往往是在它自己的行上)。如果该值是日期,则您遇到其他问题......