Reputation: 63
I have two tables where the data is not related For each row in table A i want e.g. 3 random rows in table B
This is fairly easy using a cursor, but it is awfully slow
So how can i express this in single statement to avoid RBAR ?
Upvotes: 4
Views: 1370
Reputation: 6850
Heres an example of how this could be done, code is self contained, copy and press 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
Heres an example of the output
Upvotes: 0
Reputation: 107736
To get a random number between 0 and (N-1), you can use.
abs(checksum(newid())) % N
Which means to get positive values 1-N, you use
1 + abs(checksum(newid())) % N
Note: RAND()
doesn't work - it is evaluated once per query batch and you get stuck with the same value for all rows of tableA.
The query:
SELECT *
FROM tableA A
JOIN (select *, rn=row_number() over (order by newid())
from tableB) B ON B.rn <= 1 + abs(checksum(newid())) % 9
(assuming you wanted up to 9 random rows of B per A)
Upvotes: 3
Reputation: 1269933
If you have a fixed number that you know in advance (such as 3), then:
select a.*, b.*
from a cross join
(select top 3 * from b) b
If you want a random number of rows from "b" for each row in "a", the problem is a bit harder in SQL Server.
Upvotes: 0
Reputation: 146499
assuming tableB has integer surrogate key, try
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
Upvotes: 0