Search code examples
sqlsql-server

Set every column to a corresponding column from another table, randomly selected


I have these two tables:

Table A:

id (int PK) code1 (int NOT NULL) code2 (int NOT NULL)
1 100 10
2 200 20
3 300 30

Table B:

id (int PK) code1 (int NULL) code2 (int NULL)
1 NULL NULL
2 NULL NULL
3 NULL NULL
4 NULL NULL
5 NULL NULL
6 NULL NULL
7 NULL NULL
8 NULL NULL
9 NULL NULL

FK: If B.code1 and B.code2 are non-NULL, they must refer to values in A.code1 and A.code2, respectively.

The query

UPDATE B 
SET code1 = (SELECT TOP 1 code1 FROM A ORDER BY NEWID()), 
    code2 = (SELECT TOP 1 code2 FROM A ORDER BY NEWID())

sets every row in B to the same code1 and code2 selected from A, but those two values are indeed randomly selected.

Is there a way to bulk-update every row in B so that each B.code1 and B.code2 is set to different randomly selected values from A.code1 and A.code2 without issuing a different UPDATE query for each B.id?

E.g.:

Table B:

id (int PK) code1 (int NULL) code2 (int NULL)
1 100 30
2 300 20
3 100 20
4 200 10
5 300 30
6 200 10
7 200 10
8 100 30
9 100 20

Solution

  • Simple variation

    with randomA as(
    select * 
        ,row_number()over(order by NEWID()) rn1
        ,row_number()over(order by NEWID()) rn2
        ,count(*)over()cntA
    from A
    )
    update B
      set code1=a1.code1,code2=a2.code2
    from(
      select * ,row_number()over(order by id)rnB
      from B
      )b
    left join randomA a1 on a1.rn1=(b.rnB%a1.cntA+1)
    left join randomA a2 on a2.rn2=(b.rnB%a2.cntA+1)
    

    Fiddle