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
以下是我在输出中的内容:
提前谢谢!
答案 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_n
,count_n
和volumn_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
子句中删除条件。如果你还有其他的东西,你可能不得不反对。我也怀疑通过声称是时间戳的事物进行分组的有用性,因为这些通常对于聚合中的有用组来说分辨率太高(即 - 每个值往往是在它自己的行上)。如果该值是日期,则您遇到其他问题......