在 oracle 中对具有空值的列求和
Posted
技术标签:
【中文标题】在 oracle 中对具有空值的列求和【英文标题】:Sum columns with null values in oracle 【发布时间】:2009-02-26 13:30:50 【问题描述】:我想将两个数字相加,但是当其中一个数字为空时,结果为空。有没有解决的办法。我可以简单地在代码中完成,但我宁愿在查询中完成。这是一个 oracle 数据库。
表结构
hours_t
type craft regular overtime
A 1 5 0
A 1 3 1
B 2 9 <null>
B 1 4 4
查询
select type, craft, sum(regular + overtime) as total_hours
from hours_t
group by type, craft
order by type, craft
不想要的结果
type craft total_hours
A 1 9
B 1 8
B 2 <null>
想要的结果
type craft total_hours
A 1 9
B 1 8
B 2 9
【问题讨论】:
顺便说一句,如果给出了答案,请不要删除您的 cmets ;) 我删除了评论,因为答案已更改。 【参考方案1】:NVL(value, default) 是您要查找的函数。
select type, craft, sum(NVL(regular, 0) + NVL(overtime, 0) ) as total_hours
from hours_t
group by type, craft
order by type, craft
Oracle 有 5 个与 NULL 相关的函数:
-
NVL
NVL2
结合
NULLIF
LNNVL
NVL:
NVL(expr1, expr2)
NVL 允许您在查询结果中将 null(返回为空白)替换为字符串。如果 expr1 为空,则 NVL 返回 expr2。如果 expr1 不为 null,则 NVL 返回 expr1。
NVL2:
NVL2(expr1, expr2, expr3)
NVL2 允许您根据指定表达式是否为空来确定查询返回的值。如果 expr1 不为空,则 NVL2 返回 expr2。如果 expr1 为 null,则 NVL2 返回 expr3。
COALESCE
COALESCE(expr1, expr2, ...)
COALESCE 返回表达式列表中的第一个非空 expr。至少一个 expr 不能是文字 NULL。如果所有出现的 expr 评估为 null,则该函数返回 null。
NULLIF
NULLIF(expr1, expr2)
NULLIF 比较 expr1 和 expr2。如果它们相等,则函数返回 null。如果它们不相等,则函数返回 expr1。您不能为 expr1 指定文字 NULL。
LNNVL
LNNVL(condition)
当条件的一个或两个操作数可能为空时,LNNVL 提供了一种评估条件的简洁方法。
更多信息Oracle SQL Functions
【讨论】:
为了完整起见,您可以加入 CASE 和 DECODE ;)【参考方案2】:select type, craft, sum(nvl(regular,0) + nvl(overtime,0)) as total_hours
from hours_t
group by type, craft
order by type, craft
【讨论】:
【参考方案3】:关于使用 nvl() 的其他答案是正确的,但似乎没有一个答案更突出:
您甚至应该在此列中使用 NULL 吗?
它们是否还有 0 以外的含义?
这似乎是一种情况,您应该在 th 列上有一个 NOT NULL DEFAULT 0
【讨论】:
SO的第一个目标应该是回答OP。程序员有需求。这需要回答一个问题。你甚至不知道 BerekBryan 是否有能力改变列?他有没有遇到能改变它的人?我知道我们都想展示我们有多聪明,但让我们坚持 OP @Mark Brady,我不太同意。这不是“我们有多聪明”,而是建议解决问题的替代方法。 OP 可能有也可能没有更改列的能力,但评论很有用(如果不是对他,那么可能对其他阅读此线程的人)。 @cletus,我认为这更适合作为对问题的评论而不是单独的答案。 @Mark:您可以同时回答 OP 并建议更好的方法。它可以提供更好的答案。 考虑一下:加班报告来晚了。 0 表示 - 期间没有加班,NULL 表示 - 我们没有获得给定期间的信息。如果没有 NULL,您需要额外的字段来获取我们没有获取数据的“类型”列表。【参考方案4】:NVL 评分最高的答案是完全有效的。如果您有兴趣使 SQL 代码更具可移植性,您可能需要使用 CASE,它在 Oracle 和 SQL Server 中都支持相同的语法:
select
type,craft,
SUM(
case when regular is null
then 0
else regular
end
+
case when overtime is null
then 0
else overtime
end
) as total_hours
from
hours_t
group by
type
,craft
order by
type
,craft
【讨论】:
【参考方案5】:在某些情况下,nvl(sum(column_name),0) 也是必需的。您可能需要考虑您的场景。
例如, 我正在尝试根据特定条件从特定表中获取特定列的总和。根据条件,
-
表中存在一行或多行。在这种情况下,我想要总和。
行不存在。在这种情况下,我想要 0。
如果你在这里使用 sum(nvl(column_name,0)),它会给你 null。 你可能想要的是 nvl(sum(column_name),0)。
这可能是必需的,尤其是当您将此结果传递给 java 时,将数据类型设为数字,因为这样就不需要特殊的 null 处理。
【讨论】:
你能解释一下为什么你说“如果你在这里使用 sum(nvl(column_name,0)),它会给你 null”?如果该列为空,则值为 0,因此总和中包含 0,不是吗? @Mark - “2. 行不存在。”所以 sum(nvl(column_name,0)) 有 0 行要处理,结果为 NULL。试试“SELECT sum(1) FROM dual WHERE 1=2;”【参考方案6】:您需要使用NVL功能,例如
SUM(NVL(regular,0) + NVL(overtime,0))
【讨论】:
【参考方案7】:select type, craft, sum(NVL(regular, 0) + NVL(overtime, 0)) as total_hours
from hours_t
group by type, craft
order by type, craft
【讨论】:
【参考方案8】:代码:
select type, craft, sum(coalesce( regular + overtime, regular, overtime)) as total_hours
from hours_t
group by type, craft
order by type, craft
【讨论】:
如果您对代码进行一些格式化并解释它对那些有兴趣了解您的答案如何工作的人的作用,这会有所帮助【参考方案9】:没有SUM(NVL(regular, 0) + NVL(overtime, 0))
的分组会抛出一个错误,为了避免这种情况我们可以简单地使用NVL(regular, 0) + NVL(overtime, 0)
【讨论】:
以上是关于在 oracle 中对具有空值的列求和的主要内容,如果未能解决你的问题,请参考以下文章