所有的名字应该随机匹配,当我试图再次运行查询时,名字应该与他人的名字匹配。不匹配FIRST time match
例如,我在一个表中有6条记录…
名字列看起来像:
JHON
LEE
SAM
HARRY
JIM
KRUK
所以我想要像
这样的结果First name1 First name2
Jhon. Harry
LEE. KRUK
HARRY SAM
最简单的解决方案是首先对记录进行随机排序,然后计算分组和组内的序列号,最后选择出组作为行。
您可以按照下面的逻辑操作:https://dbfiddle.uk/9JlK59w4
DECLARE @Sorted TABLE
(
Id INT PRIMARY KEY,
FirstName varchar(30),
RowNum INT IDENTITY(1,1)
);
INSERT INTO @Sorted (Id, FirstName)
SELECT Id, FirstName
FROM People
ORDER BY NEWID();
WITH Pairs as
(
SELECT *
, (RowNum+1)/2 as PairNum
, RowNum % 2 as Ordinal
FROM @Sorted
)
SELECT
Person1.FirstName as [First name1], Person2.FirstName as [First name2]
FROM Pairs Person1
LEFT JOIN Pairs Person2 ON Person1.PairNum = Person2.PairNum AND Person2.Ordinal = 1
WHERE Person1.Ordinal = 0
ORDER BY Person1.PairNum
这里使用ORDER BY NEWID()
对记录进行随机排序。注意,它是不确定的,每次执行都会返回一个新值。虽然效率不高,但符合我们的要求。您不能轻易地使用CTE生成随机排序记录的列表,因为CTE的结果是而不是缓存。每次在后续逻辑中引用CTE时,都会导致对表达式重新求值。运行这个工具几次,看看它是如何不正确地分配名称的:https://dbfiddle.uk/rpPdkkAG
由于
NEWID()
的波动性,本例将结果存储在表值变量中。对于非常大的记录列表,临时表可能更有效。
的群号。PairNum
使用简单的除以n逻辑分配长度为n- 有必要将1添加到
RowNum
,因为整数数学将四舍五入,在小提琴中看到这一点。
- 有必要将1添加到
Ordinal
使用RowNumber上的模,是一个值,我们可以用它来区分Person 1和Person 2。这有助于我们保持逻辑的其余部分是确定的。
在最终的SELECT
中,我们首先从Pairs
中选择具有0
的Ordinal
,然后我们加入具有1
的Ordinal
与PairNum
匹配的Pairs
您可以看到,我添加了一个使用3个组的解决方案,以展示如何轻松地扩展到更大的组。