在 oracle 中的 case 或 decode 语句中使用 sum
Posted
技术标签:
【中文标题】在 oracle 中的 case 或 decode 语句中使用 sum【英文标题】:Using sum inside a case or decode statement in oracle 【发布时间】:2014-09-19 11:20:47 【问题描述】:我试图寻找线索,但在任何地方都没有得到满意的答案。
我的问题是我有一个巨大的 select 语句,其中几乎一半的列来自子查询,在这些子查询中我必须检查很多东西。
我知道 oracle 在聚合函数方面是严格的,但是当我在其中一个子查询中尝试这样的事情时,我得到了预期的输出:
SELECT DECODE(NVL(SUM(Qty1),0),0,SUM(Qty2),SUM(Qty1))
FROM test_v
WHERE item_no = 1234567;
但奇怪的是,当我将其修改为:
SELECT
DECODE(FLAG,1,SUM(Qty2),SUM(Qty1))
FROM test_v
WHERE item_no = 1234567;
我收到此错误:
ORA-00937: not a single-group group function
00937. 00000 - "not a single-group group function"
*Cause:
*Action:
Error at Line: 9 Column: 8`
为什么它在两个几乎相似的查询中给出不同的结果。我知道它可以通过使用GROUP BY
来解决,但是当我在输出中没有得到任何其他列时,我该如何决定GROUP BY
子句。
我还继续尝试使用这样的CASE
声明,但没有用:
SELECT
CASE
WHEN flag = 1 THEN
SUM(Qty2)
WHEN flag = 0 THEN
SUM(Qty1)
END Qty
FROM test_v
WHERE item_no = 1234567;
我仍然遇到同样的错误。
我知道我可以通过使用另一个子查询来计算 SUM 来覆盖这一点,但这就像生活在一个 select 中的几代子查询一样,出于审美、性能和个人原因,我不希望过度使用子查询。
任何想法为什么第一个有效而这无效??
【问题讨论】:
【参考方案1】:这是产生错误的查询:
SELECT DECODE(FLAG, 1, SUM(Qty2), SUM(Qty1))
FROM test_v
WHERE item_no = 1234567;
这是一个聚合查询。没有group by
,结果集中只有一组,汇总所有数据。
问题是flag
不在聚合函数中。应该使用哪个值?每行都有一个。这就是为什么 SQL(通常)要求聚合查询中的所有表达式都必须是聚合函数,group by
中提到的列除外。
以下方法可行:
SELECT DECODE(MAX(FLAG), 1, SUM(Qty2), SUM(Qty1))
FROM test_v
WHERE item_no = 1234567;
注意:我使用 decode()
只是因为它在您的示例查询中。你应该学会使用case
。
【讨论】:
哇!这东西行得通! :) :) 并指出先生..将使用case
语句而不是解码!感谢您这么快分享这么棒的技巧! :)
@Neels:如果您认为这是一个技巧,那么您应该真的阅读 SQL 中的聚合。 Gordon 只是向您展示了一种 方法来使语句在句法上 正确。这真的恰好是您正在寻找的查询吗?您甚至了解 Gordon 的查询是如何工作的吗?
@ThorstenKettner:嗯,这里使用的聚合适用于我的情况(显然我不能展示我的整个代码来证明我理解)。了解戈登的询问中发生的事情并不是一门火箭科学。不要认为我在语法方面错了,只是错过了使用正确的聚合!而且我仍然会称其为技巧,因为在不影响结果的情况下,这会带来解决方案。
@Neels:正如 Gordon 所说,应该使用哪个记录的标志?他展示了一种方法,当至少一条记录具有标志 1 时,总和为 qty2。当没有记录具有标志 0 时,或者当超过 50% 的记录具有标志 1 时,他也可以展示一种方法。当您不关心单个值时,为什么每条记录中甚至还有一个标志(如:对于标记为 1 sum qty2 的每条记录,对于其他总和 qty1)?因为这恰好是适合您的解决方案,好吧。但是当你把它当作一个把戏时,你似乎没有理解正在发生的事情以及还有哪些其他选择。对不起。
@ThorstenKettner:好的.. 只是让你知道,我的实际查询类似于SELECT CASE WHEN max(a.flag) = 1 THEN SUM(a.qty2) WHEN max(a.flag) = 0 THEN decode(nvl(sum(a.qty1),0),0,sum(a.qty2),sum(a.qty1)) END qty FROM test_v WHERE item_no = 1234567 AND flag= i_flag
这个i_flag
被动态传递到这个查询中。这可能不是最好的解决方案,但我知道发生了什么! :)以上是关于在 oracle 中的 case 或 decode 语句中使用 sum的主要内容,如果未能解决你的问题,请参考以下文章