3

サンプルデータでデータベースを作成しています。ストアド プロシージャを実行してサンプル データベース用の新しいデータを生成するたびに、テーブル A (「製品」) のすべての行に基づいて、テーブル B (「アイテム」) を消去して再入力したいと考えています。

テーブル A に主キーの値が 1、2、3、4、および 5 の行が含まれている場合、テーブル B にテーブル A の外部キーを設定し、テーブル A の行ごとに乱数の行をテーブル B に挿入する必要があります。(基本的に、任意の「製品」に対してランダムな数の「アイテム」を棚にストックしています。)

この回答のコードを使用して、数字のリストを生成しています。この関数の結果に結合して、挿入する行を作成します。

WITH cte AS
(
   SELECT
       ROW_NUMBER() OVER (ORDER BY (select 0)) AS i
   FROM
      sys.columns c1 CROSS JOIN sys.columns c2 CROSS JOIN sys.columns c3
)
SELECT i
FROM cte
WHERE 
    i BETWEEN @p_Min AND @p_Max AND
    i % @p_Increment = 0

乱数は、次のように (関数の制限を回避するために) ビューで生成されます。

-- Mock.NewGuid view
SELECT id = ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)))

そして、乱数を返す関数:

-- Mock.GetRandomInt(min, max) function definition
DECLARE @random int;
SELECT @random = Id % (@MaxValue - @MinValue + 1) FROM Mock.NewGuid;
RETURN @random + @MinValue;

しかし、このコードを見て実行すると...

WITH Products AS
(
    SELECT ProductId, ItemCount = Mock.GetRandomInt(1,5)
    FROM Product.Product
)
SELECT A = Products.ProductId, B = i
FROM Products
JOIN (SELECT i FROM Mock.GetIntList(1,5,1)) Temp ON
    i < Products.ItemCount
ORDER BY ProductId, i

...これは一貫性のない結果を返します!

A,B
1,1
1,2
1,3
2,1
2,2
3,2 <-- where is 1?
3,3
4,1
5,3 <-- where is 1, 2?
6,1

すべての製品 ID について、JOIN の結果は 1 ~ 5 行になると予想されます。ただし、値がスキップされるようです。これは、大規模なデータ セットではさらに顕著になります。もともと、商品行ごとにアイテムで 20 ~ 50 行を生成しようとしていましたが、これにより、商品ごとに 30 ~ 40 行しか生成されませんでした。

質問:なぜこれが起こっているのか分かりますか? 各製品にはランダムな行数 (1 から 5 の間) が挿入され、B 値は連続している必要があります。代わりに、一部の数値が欠落しています。

この問題は、作成したテーブルに数値を格納してからそれに結合した場合、または再帰 CTE を使用した場合にも発生します。

SQL Server 2008R2 を使用していますが、2012 データベースでも同じ問題が発生していると思います。互換性レベルはそれぞれ 2008 と 2012 です。

4

2 に答える 2