0

我对 SQL 比较陌生,但我拥有良好的编程经验。我有一段代码让我创建一个将值返回到表中的“函数”。但是,当代码尝试比较两组数据以给出百分比差异时,我遇到了 NULLS 的问题。如果一组数据全部为 NULLS,则在 INSERT 上不会发生联接,因此尽管确实存在 100% 的差异,但它什么也不返回。我想添加一个 IF 语句,这样如果其中一组数据的计数为零(它们都是空值),那么它会默认一个值,如果有 2 组真正的数据,那么它会加入 2 组并计算?希望这足以解释它。下面是大部分代码 - 如果没有数据,DS1VALS 或 DS2VALS 将不会返回任何内容。我已经尝试了该区域的几乎所有方法来添加 IF EXISTS 或 ISNULL 但没有任何效果。我确实收到一条消息,提示 FUNCTION 不能将答案返回给 IF 等???谢谢。

-- get the PeriodicDataElementInstanceID for the datasources that we're using
select @DataSource1_PDEIID = PeriodicDataElementInstanceID
from PeriodicDataElementInstance
where Name = @DS1

select @DataSource2_PDEIID = PeriodicDataElementInstanceID
from PeriodicDataElementInstance
where Name = @DS2

-- get the start and end date of the periods in the past that we are checking.
-- these are based on the Calendar, calendar period type, and system start date set in the Universal
-- system options.
select @fromDate = StartDate
from dbo.GetPeriodsDateByPeriodsOffset(@X)

select @toDate = EndDate
from dbo.GetPeriodsDateByPeriodsOffset(@Y)

select @fromDate2 = StartDate 
from dbo.GetPeriodsDateByPeriodsOffset(@XX) 

select @todate2 = EndDate 
from dbo.GetPeriodsDateByPeriodsOffset(@YY) 

;with
DS1VALS (EI, Value) as
(select pds.EndItemID, sum(pd.value)
from PeriodicDataStream pds 
join PeriodicData pd on pd.PeriodicDataStreamID = pds.PeriodicDataStreamID
where pds.PeriodicDataElementInstanceID = @DataSource1_PDEIID
and pd.PeriodDate between @fromDate and @todate
group by pds.EndItemID),
DS2VALS (EI, Value) as
(select pds.EndItemID, sum(pd.value)
from PeriodicDataStream pds 
join PeriodicData pd on pd.PeriodicDataStreamID = pds.PeriodicDataStreamID
where pds.PeriodicDataElementInstanceID = @DataSource2_PDEIID
and pd.PeriodDate between @fromDate2 and @todate2 
group by pds.EndItemID)

--select * from DS1VALS ds1
--join DS2VALS ds2 on ds1.EI = ds2.EI

Insert into @Results
select ds1.EI,  
    case 
    when (convert(numeric(19,9),ds1.Value) <> 0)
    then (convert(numeric(19,9),ds2.Value) / convert(numeric(19,9),ds1.Value) - 1) * 100
    else 9999999999
    end
from DS1VALS ds1
join DS2VALS ds2 on ds1.EI = ds2.EI
where convert(numeric(19,9),ds1.Value) <> convert(numeric(19,9),ds2.Value);

Return
End
4

1 回答 1

0

我将假设以下内容:

  • Number2/Number1 = 分数/百分比
  • 0/Number1 = 0(与 Number2/Number1 的结果相同,因此不需要特殊情况)
  • Number2/0 = 错误,你想显示 9999999999
  • NULL/数字1 = 0
  • Number2/NULL = 与除以零相同

从上面可以看出,如果任一侧为NULL,则将其视为零。您的解决方案是将 NULL 转换为零:

CASE
    WHEN ISNULL(convert(numeric(19,9),ds1.Value), 0) = 0 THEN 9999999999
    ELSE 
    (
        ISNULL(convert(numeric(19,9),ds2.Value), 0) 
        / convert(numeric(19,9),ds1.Value) 
        - 1
    )
    * 100
END

更新:根据反馈,以下内容也需要更改:

FROM DS1VALS ds1
FULL OUTER JOIN DS2VALS ds2 ON ds1.EI = ds2.EI
WHERE ISNULL(convert(numeric(19,9),ds1.Value), 0) <> ISNULL(convert(numeric(19,9),ds2.Value), 0);

请注意,连接现在是一个FULL OUTER JOIN. 这将尽可能匹配行,仅包括没有匹配右侧的左侧,以及没有匹配左侧的右侧。

您必须小心,您的WHERE子句不会强制您的连接像一个INNER JOIN但一样工作。

于 2013-09-17T02:42:01.630 回答