2

ある手順で、最初は間違っていると思っていたいくつかのステートメントを見つけましたが、それらをテストした後、それらが正常に機能していることを確信しました。私が理解できないのは方法です。

record idpts、およびptsOf列を持つ単純なテーブルがあります。

DECLARE @DataSource TABLE
(
     RecordID TINYINT
    ,Pts   INT
    ,PtsOf INT
)

INSERT INTO @DataSource
VALUES (1,5,5)
      ,(1,7,8)
      ,(1,3,5)
      ,(2,5,0)

そして、次の式を使用して各レコードの合計スコアを計算する必要があります。

SUM(pts)/SUM(ptsOf) * 100

したがって、最後のレコードには5/0があるため、上記のステートメントは次のエラーを生成します。

メッセージ 8134、レベル 16、状態 1、行 21 ゼロ除算エラーが発生しました。

しかし、私が見つけたステートメントでは、 select句でのみゼロ除算がチェックされ、 order by句ではチェックされません。

 SELECT  RecordID
         ,CAST(CAST(SUM(Pts) AS decimal) / CASE SUM(PtsOf) WHEN 0 THEN NULL ELSE SUM(PtsOf) END * 100 AS decimal(18, 0))
 FROM @DataSource
 GROUP BY RecordID
 ORDER BY RecordID,  CAST(CAST(SUM(Pts) AS decimal) / SUM(PtsOf) * 100 AS decimal(18, 0)) ASC

クラスごとの順序での計算でエラーが発生しないのはなぜですか?

以下は完全な例です。

SET NOCOUNT ON
GO

    DECLARE @DataSource TABLE
    (
         RecordID TINYINT
        ,Pts   INT
        ,PtsOf INT
    )

    INSERT INTO @DataSource
    VALUES (1,5,5)
          ,(1,7,8)
          ,(1,3,5)
          ,(2,5,0)

     SELECT  RecordID
             ,CAST(CAST(SUM(Pts) AS decimal) / CASE SUM(PtsOf) WHEN 0 THEN NULL ELSE SUM(PtsOf) END * 100 AS decimal(18, 0))
     FROM @DataSource
     GROUP BY RecordID
     ORDER BY RecordID,  CAST(CAST(SUM(Pts) AS decimal) / SUM(PtsOf) * 100 AS decimal(18, 0)) ASC

SET NOCOUNT OFF
GO
4

1 に答える 1

3

I believe that the second clause in the ORDER BY is simply ignored in this particular case. After all if you do this:

DECLARE @t TABLE(i INT PRIMARY KEY, x UNIQUEIDENTIFIER);

INSERT @t VALUES(1,NEWID()),(2,NEWID()),(3,NEWID()),(4,NEWID());

SELECT i, x FROM @t ORDER BY i, x;

x is not considered in the ORDER BY, and why should it be? The first entity in the ORDER BY clause already dictates the order, and the second clause can't change it. Since you're grouping by RecordID, SQL Server is smart enough to realize that the first element in the ORDER BY is unique, so it doesn't need to consider the second. I can't prove that, and I can make it fail when the second element is actually much more clear to SQL Server by using a constant, e.g.:

ORDER BY RecordID, CONVERT(1/0);

But when the output of the column is not easily known to SQL Server, and it can't do anything useful with the output anyway, it does the right thing (IMHO) and discards the expression without fully evaluating it and causing the runtime error. You can also make the error return if you don't first order by a column that is guaranteed to be unique:

ORDER BY CAST(CAST(SUM(Pts) AS decimal) / SUM(PtsOf) * 100 AS decimal(18, 0));
于 2013-03-29T18:11:22.323 に答える