0

私は SQL には比較的慣れていませんが、優れたプログラミング経験があります。テーブルに値を返す「関数」を作成するために与えられたコードがあります。ただし、コードが2セットのデータを比較してパーセンテージの違いを求めようとしている場合、NULLSに問題があります。データの 1 つのセットがすべて NULLS の場合、INSERT で Join を実行できないため、実際には 100% の違いがありますが、何も返されません。IF ステートメントを追加して、データ セットの 1 つのカウントがゼロの場合 (それらはすべて null でした)、デフォルト値を設定し、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

私は次のことを仮定します:

  • 数値 2/数値 1 = 分数/パーセント
  • 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 に答える