0

次のようなクエリがあり、パーセンテージを取得しています。

SELECT SUM(convert(decimal(3,2),
          CASE WHEN Status_ID = 1 AND State_ID = 14 THEN 1 ELSE 0 END))/
          SUM(convert(decimal(3,2),CASE WHEN State_ID = 14 THEN 1 ELSE 0 END)) * 100
FROM SomeTable

通常、これは 59.77803 のような値を返します。しかし、2 番目の SUM (分母) が 0 になる可能性がある (当然のことながら) ケースがあることがわかります。このケースを説明し、0 による除算の例外を回避する方法を知っている人はいますか?

SQL Server 2005 を使用しています。ありがとうございます。

4

6 に答える 6

2

私はおそらく NULL を使用して計算不能を表しますが、それは問題のドメインでの意図に依存します (コードは何が起こっているかを示すために展開されています)。

SELECT SUM(convert(decimal(3,2),
                   CASE WHEN Status_ID = 1 AND State_ID = 14 THEN 1 ELSE 0 END)
          )
       /
       NULLIF(
           SUM(convert(decimal(3,2),
                       CASE WHEN State_ID = 14 THEN 1 ELSE 0 END)
           )
           , 0
       )
       * 100
FROM SomeTable

テーブルに行がないため分母がゼロになる結果は、NULL に変換されるため、式全体が NULL になります。

そのコードも少し単純化できます (おそらく、すでに単純化されたおもちゃの問題だからです)。

SELECT SUM( convert(decimal(3,2), CASE WHEN Status_ID = 1 THEN 1 ELSE 0 END) )
       /
       NULLIF( convert(decimal(3,2), COUNT(*)), 0 )
       * 100
FROM SomeTable
WHERE State_ID = 14

多数の異なるものを 1 つのクエリに結合する例として、次のようにします。

SELECT CASE WHEN State_ID = 14 THEN 'State_ID = 14'
            WHEN State_ID IN (1, 2, 3) THEN 'State_ID IN (1, 2, 3)'
            ELSE 'DEFAULT'
       END AS Category
       ,SUM(convert(decimal(3,2),
                   CASE WHEN Status_ID = 1 THEN 1 ELSE 0 END)
          )
       /
       convert(decimal(3,2), COUNT(*))
       * 100
FROM SomeTable
GROUP BY CASE WHEN State_ID = 14 THEN 'State_ID = 14'
            WHEN State_ID IN (1, 2, 3) THEN 'State_ID IN (1, 2, 3)'
            ELSE 'DEFAULT'
       END
于 2010-08-18T20:36:41.503 に答える
1

分母が 0 の場合に何を返したいか自問してみてください。
それに基づいて、それに応じてクエリを修正します。

それを行うための適切な組み込みの方法はありません。ビジネスロジックの話です。

于 2010-08-18T19:58:01.940 に答える
1

私がそれを正しく読んでいれば、これはうまくいくはずです:

SELECT SUM(convert(decimal(3,2), 
          CASE WHEN Status_ID = 1 THEN 1 ELSE 0 END))/ 
          SUM(convert(decimal(3,2),1)) * 100 
FROM SomeTable 
WHERE State_ID = 14 
于 2010-08-18T20:00:37.520 に答える
0

0 例外による除算を回避するには、分子、分母、および分母が 0 の場合に渡すデフォルト値を受け入れる関数を使用できます。そして、その関数を呼び出して除算を行います。

CREATE FUNCTION [dbo].[fn_divide] 
(
    @numerator DECIMAL(3,2),@denominator DECIMAL(3,2),@default DECIMAL(3,2)
)  
RETURNS DECIMAL(3,2) 

AS  BEGIN

 DECLARE @result DECIMAL(3,2)

 IF @denominator = 0
 BEGIN
    set @result=@default
 END
ELSE
 BEGIN
    set @result=@numerator/@denominator
 END 

  return @result
END
于 2010-08-18T20:11:56.347 に答える
0
SELECT SUM(convert(decimal(3,2),
          CASE WHEN Status_ID = 1 AND State_ID = 14 THEN 1 ELSE 0 END))/
          SUM(convert(decimal(3,2),CASE WHEN State_ID = 14 THEN 1 ELSE 0 END)) + 0.00000000001 * 100
FROM SomeTable
于 2010-08-18T19:56:21.973 に答える
0

本当の問題は、ゼロで割ろうとするときの「答え」はどうあるべきかということです。私はそれを作るのでNULL、次のようなことを試してください:

DECLARE @x int

set @x=5
select 1.0/NULLIF(@x,0)

set @x=0
select 1.0/NULLIF(@x,0)

出力:

---------------------------------------
0.200000000000

(1 row(s) affected)


---------------------------------------
NULL

(1 row(s) affected)

あなたのコードは次のようになります。

SELECT SUM(convert(decimal(3,2), CASE
                                     WHEN Status_ID = 1 AND State_ID = 14 THEN 1 
                                     ELSE 0 
                                 END
                  )
          ) 
        /
        SUM(convert(decimal(3,2),CASE
                                     WHEN State_ID = 14 THEN 1 
                                     ELSE NULL   --<<<<<<<<<<<<force null if div by zero
                                 END
                   )
           )
        * 100
FROM SomeTable

よくわかりませんがWHEN Status_ID = 1 AND State_ID = 14 THEN 1、それがOPコードです。

于 2010-08-18T20:25:27.463 に答える