SOの質問は、私を次の質問に導きました。
テーブルに16行ある場合、ランダムに配置された番号1、2、3、4、5、...、16のフィールドをテーブルに追加します。つまり、行1の「RndVal」フィールドに次のようになります。 2、次に行2の場合は5になる可能性があります。つまり、16個の整数のそれぞれが繰り返しなしで1回出現する必要があります。
次の機能が機能しないのはなぜですか?理想的には、これが機能することを確認してから、代替ソリューションを確認したいと思います。
これにより、テーブルが正常に作成されます。
IF OBJECT_ID('tempdb..#A') IS NOT NULL BEGIN DROP TABLE #A END
IF OBJECT_ID('tempdb..#B') IS NOT NULL BEGIN DROP TABLE #B END
IF OBJECT_ID('tempdb..#C') IS NOT NULL BEGIN DROP TABLE #C END
IF OBJECT_ID('tempdb..#myTable') IS NOT NULL BEGIN DROP TABLE #myTable END
CREATE TABLE #B (B_ID INT)
CREATE TABLE #C (C_ID INT)
INSERT INTO #B(B_ID) VALUES
(10),
(20),
(30),
(40)
INSERT INTO #C(C_ID)VALUES
(1),
(2),
(3),
(4)
CREATE TABLE #A
(
B_ID INT
, C_ID INT
, RndVal INT
)
INSERT INTO #A(B_ID, C_ID, RndVal)
SELECT
#B.B_ID
, #C.C_ID
, 0
FROM #B CROSS JOIN #C;
次に、以下を使用してランダム列を追加しようとしています。ロジックは、1から16までの乱数を追加し、ループ内で他の数値と重複しているものを効果的に上書きすることです。
SELECT
ROW_NUMBER() OVER(ORDER BY B_ID) AS Row
, B_ID
, C_ID
, RndVal
INTO #myTable
FROM #A
DECLARE @rowsRequired INT = (SELECT COUNT(*) CNT FROM #myTable)
DECLARE @i INT = (SELECT @rowsRequired - SUM(CASE WHEN RndVal > 0 THEN 1 ELSE 0 END) FROM #myTable)--0
DECLARE @end INT = 1
WHILE @end > 0
BEGIN
SELECT @i = @rowsRequired - SUM(CASE WHEN RndVal > 0 THEN 1 ELSE 0 END) FROM #myTable
WHILE @i>0
BEGIN
UPDATE x
SET x.RndVal = FLOOR(RAND()*@rowsRequired)
FROM #myTable x
WHERE x.RndVal = 0
SET @i = @i-1
END
--this is to remove possible duplicates
UPDATE c
SET c.RndVal = 0
FROM
#myTable c
INNER JOIN
(
SELECT RndVal
FROM #myTable
GROUP BY RndVal
HAVING COUNT(RndVal)>1
) t
ON
c.RndVal = t.RndVal
SET @end = @@ROWCOUNT
END
TRUNCATE TABLE #A
INSERT INTO #A
SELECT
B_ID
, C_ID
, RndVal
FROM #myTable
元のテーブルに6行ある場合、結果は次のようになります。
B_ID|C_ID|RndVal
----------------
| | 5
| | 4
| | 1
| | 6
| | 3
| | 2