联接除法时滤除NULL值

时间:2018-08-14 15:00:06

标签: sql-server

我正在尝试查找内部连接在同一表上的不同类型的盒子在4个月内的实际重量和预测重量之间的百分比差异。如果我要对t1和t2进行翻转,则代码可以工作,但是我需要t1作为分母。但是,t1有一些NULL值,因此代码会终止,因为在某些情况下它会被零除。如何过滤出NULL值以便可以创建表? Join看起来像这样:

select t1.box_type,
   abs((t1.D1 - t2.D1)/t1.D1)*100 as Diff1,
   abs((t1.D2 - t2.D2)/t1.D2)*100 as Diff2,
   abs((t1.D3 - t2.D3)/t1.D3)*100 as Diff3,
   abs((t1.D4 - t2.D4)/t1.D4)*100 as Diff4
from Boxes t1
  join Boxes t2 on t1.box_type = t2.box_type
where t1.DataCategory IS NOT NULL
  and t1.DataCategory = 'actual' 
  and t2.DataCategory = 'forecast'

IS NOT NULL不会阻止代码包含NULL值。我可以在代码前面过滤掉NULL值还是需要编写一个新脚本?

以下是数据示例:

Data     | Box_Type | D1 | D2   | D3 | D4
Actual        L       8    NULL   9    8
Forecast      L       7    7      8    8
Actual        M       NULL 6      7    7
Forecast      M       5    6      6    7
Actual        S       4    4      3    NULL
Forecast      S       4    3      3    6

2 个答案:

答案 0 :(得分:0)

您可以在代码的前面过滤掉NULL值,并避免出现“被零除”错误。

在CTE中过滤掉NULL,然后从该CTE中进行选择。

答案 1 :(得分:0)

如果您滤除NULL值,则可能无法计算该行其他列的差异。相反,您可能想尝试使用CASE表达式。假设如果t1的列为NULL,则您希望有0%的差异,那么查询将看起来像这样。

select t1.box_type,
   case when t1.D1 is null then 0 else abs((t1.D1 - t2.D1)/t1.D1)*100 end as Diff1,
   case when t1.D2 is null then 0 else abs((t1.D2 - t2.D2)/t1.D2)*100 end as Diff2,
   case when t1.D3 is null then 0 else abs((t1.D3 - t2.D3)/t1.D3)*100 end as Diff3,
   case when t1.D4 is null then 0 else abs((t1.D4 - t2.D4)/t1.D4)*100 end as Diff4
from Boxes t1
  join Boxes t2 on t1.box_type = t2.box_type
where t1.DataCategory IS NOT NULL
  and t1.DataCategory = 'actual' 
  and t2.DataCategory = 'forecast'