データが関連していない2つのテーブルがありますテーブルAの各行について、テーブルBの3つのランダムな行が必要です
これはカーソルを使用するとかなり簡単ですが、非常に遅いです
では、これを単一のステートメントで表現して RBAR を回避するにはどうすればよいでしょうか?
データが関連していない2つのテーブルがありますテーブルAの各行について、テーブルBの3つのランダムな行が必要です
これはカーソルを使用するとかなり簡単ですが、非常に遅いです
では、これを単一のステートメントで表現して RBAR を回避するにはどうすればよいでしょうか?
0 から (N-1) までの乱数を取得するには、次を使用できます。
abs(checksum(newid())) % N
つまり、正の値 1 ~ N を取得するには、次を使用します。
1 + abs(checksum(newid())) % N
注:RAND()
機能しません。クエリ バッチごとに 1 回評価され、tableA のすべての行で同じ値に固執します。
クエリ:
SELECT *
FROM tableA A
JOIN (select *, rn=row_number() over (order by newid())
from tableB) B ON B.rn <= 1 + abs(checksum(newid())) % 9
(A ごとに最大 9 つのランダムな行の B が必要であると仮定します)
tableBに整数の代理キーがあると仮定して、試してください
Declare @maxRecs integer = 11 -- Maximum number of b records per a record
Select a.*, b.*
From tableA a Join tableB b
On b.PKColumn % (floor(Rand() * @maxRecs)) = 0
事前にわかっている固定数 (3 など) がある場合は、次のようになります。
select a.*, b.*
from a cross join
(select top 3 * from b) b
"a" の各行に対して "b" からランダムな数の行が必要な場合、SQL Server では問題が少し難しくなります。
これを行う方法の例を次に示します。コードは自己完結型で、コピーして F5 キーを押します ;)
-- create two tables we can join
DECLARE @datatable TABLE(ID INT)
DECLARE @randomtable TABLE(ID INT)
-- add some dummy data
DECLARE @i INT = 1
WHILE(@i < 3) BEGIN
INSERT INTO @datatable (ID) VALUES (@i)
SET @i = @i + 1
END
SET @i = 1
WHILE(@i < 100) BEGIN
INSERT INTO @randomtable (ID) VALUES (@i)
SET @i = @i + 1
END
--The key here being the ORDER BY newid() which makes sure that
--the TOP 3 is different every time
SELECT
d.ID AS DataID
,rtable.ID RandomRow
FROM @datatable d
LEFT JOIN (SELECT TOP 3 * FROM @randomtable ORDER BY newid()) as rtable ON 1 = 1
出力の例を次に示します