web-dev-qa-db-ja.com

確定的関数STDEV()で非確定的結果が得られるのはなぜですか?

これは私が実行しようとしているクエリのタイプです:

WITH CTE_Ordered AS
(
  SELECT *, ROW_NUMBER() OVER (PARTITION BY PartitionField ORDER BY DateField) AS PartitionRowId
  FROM SourceTable
),
CTE_Top1_PerPartition AS
(
  SELECT *
  FROM CTE_Ordered
  WHERE PartitionRowId = 1
),
CTE_Calculations AS
(
  SELECT AVG(NumberField1) AS NumberField1_Avg, StdDev.StdDev AS NumberField1_StdDev
  FROM CTE_Top1_PerPartition 
  CROSS JOIN
  (
     SELECT STDEV(NumberField1) AS StdDev
     FROM CTE_Top1_PerPartition 
  ) AS StdDev
  GROUP BY StdDev.StdDev
)

-- Final Select
SELECT *
FROM CTE_Calculations

最終選択を実行するたびに、SourceTableが分離されていて変更されていなくても、NumberField1_StdDev値が変更されます。

最初に一時テーブルにCTE_Top1_PerPartitionを選択してから、その一時テーブルから残りのクエリを実行すると、NumberField1_StdDevに対して毎回同じ結果が得られることに気付きました。

結果がCTE_Top1_PerPartition CTEで返される順序と関係があると思いますが、理由はわかりません。

5
J.D.

row_numberは、タイ(つまり、PartitionFieldDateFieldの値が同じ行)が存在する場合、確定的ではありません。関連付けられた値のいずれかがPartitionRowIdが1になる可能性があり、おそらく最終結果が変更されます。

row_numberの代わりにrankを使用することもできますが、その場合は、必要とされない可能性のあるすべての結合された行を考慮する必要があります。分析関数を更新して、order by基準を追加してrow_numberが確実に最初の行を返すようにすることもできます。

15
Justin Cave