0

SQL Server 2005 には、ツリーの最上位に到達するまで各アイテムの親を取得するテーブルをループするループがあります。

DECLARE @T Table
(
  ItemID INT NOT NULL PRIMARY KEY,
  AncestorID INT NULL 
)

次のようなデータがあります。

ItemID | AncestorID
  1          2
  2          3
  3          4
  4          NULL

基本的にこれを行うループがあります。

DECLARE @AncestorID INT
SELECT @AncestorID = 1
WHILE (@AncestorID IS NOT NULL)
BEGIN   
  --Do some work   
  SELECT @AncestorID = T.AncestorID   
  FROM @T t  
  WHERE T.ItemID = @AncestorID

  print @AncestorID
END

(はい、SQL はセットベースであり、これは行ごとに処理していることを知っています。理由により、「いくつかの作業を行う」を行ごとに実行する必要があります)。

これは、最終的に無限ループに陥る今日まで、常に正常に機能していました。原因はいくつかの間違ったデータであることがわかりました:

ItemID | AncestorID
  1          2
  2          3

  4          NULL

ItemID3を削除しました。ループは決して終了しないため、ループは決して終了しません。ループはAncestorID3NULLのままです。

クエリが 0 行を返す場合に select ステートメントを書き直して@AncestorIDnullにする方法はありますか、またはレコードといくつかの型ロジックをカウントする別のステートメントが必要ですか?SELECTSELECTIF ELSE

4

3 に答える 3

4

SELECT クエリが 0 行を返す場合、select ステートメントを書き直して @AncestorID を null にする方法はありますか?

で集計を使用できますT.AncestorID

SELECT @AncestorID = min(T.AncestorID)   
FROM @T t  
WHERE T.ItemID = @AncestorID
于 2012-09-26T03:02:27.837 に答える
2

使うBreak

例えば

WHILE (@AncestorID IS NOT NULL)
BEGIN 

  SELECT T.AncestorID INTO #TEMP 
  FROM @T t WHERE T.ItemID = @AncestorID  

  IF((SELECT COUNT(*) FROM #TEMP) = 0) BREAK;

  SELECT @AncestorID=T.AncestorID   
  FROM #TEMP  t  

  print @AncestorID

  DROP TABLE #TEMP

END
于 2012-09-26T04:37:28.177 に答える
2

たとえば、別の変数を使用して、前の値を保持し、クエリの前に@PreviousAncestorIdリセット@AncestorIdすることができます。NULL

@@RowCountクエリの後でチェックして、行が見つかったかどうかを確認できます。

コードには、データ内の任意の長さのサイクル (両方の値が同じ行など) を処理する問題がまだあります。サイクルを検出するには、訪問した行を追跡する必要があります。簡単な現実チェックは、ループの反復回数を数え、それを行数に対してチェックすることです。

于 2012-09-26T02:32:26.003 に答える