还有一个想法:使用该函数只是为您的业务逻辑进行计算并提交非确定性部分。在您的情况下,您似乎选择了一个介于零和最高员工 ID 之间的随机数(缺少 ID 怎么办?)
如前所述,RAND() 很难使用。它将在多次调用中返回相同的值。因此我使用NEWID,将其转换为VARBINARY(8),并将其转换为BIGINT。
看看这个:
此函数将采用GUID 并在给定边界之间缩放:
CREATE FUNCTION dbo.GetRandomNumber(@lowerLimit BIGINT, @upperLimit BIGINT, @GuidValue UNIQUEIDENTIFIER)
RETURNS BIGINT
AS
BEGIN
RETURN
(
SELECT ABS(CAST(CAST(@GuidValue AS VARBINARY(8)) AS BIGINT)) % (@upperLimit-@lowerLimit)+@lowerLimit
)
END
GO
--该表将被随机值填充
CREATE TABLE testTable(RndNumber BIGINT,Tile INT);
--CTE 创建超过 6 个 mio 虚拟行
WITH manyRows AS
(
SELECT 1 AS nr FROM master..spt_values CROSS JOIN master..spt_values AS x
)
INSERT INTO testTable(RndNumber)
SELECT dbo.GetRandomNumber(-300,700,NEWID()) --<-- Here I pass in the non-deterministic part
FROM manyRows;
--现在表格被平铺成10个相等的片段
WITH UpdateableCTE AS
(
SELECT Tile
,NTILE(10) OVER(ORDER BY RndNumber) AS tileValue
FROM testTable
)
UPDATE UpdateableCTE SET Tile=tileValue;
--检查随机结果
SELECT * FROM testTable
ORDER BY Tile,RndNumber;
--这清楚地表明,每个图块的覆盖范围几乎相同,这证明了相当好的随机分布
SELECT Tile
,COUNT(*) CountOfNumbers
,MAX(RndNumber)-MIN(RndNumber) CoveredRange
FROM testTable
GROUP BY Tile
ORDER BY Tile;
GO
--清理
DROP TABLE dbo.testTable;
DROP FUNCTION dbo.GetRandomNumber;
结果
T Counts min max CoveredRange
1 636553 -300 -201 99
2 636553 -201 -101 100
3 636553 -101 0 101
4 636553 0 99 99
5 636553 99 199 100
6 636553 199 299 100
7 636553 299 399 100
8 636553 399 499 100
9 636553 499 599 100
10 636552 599 699 100
您可以看到,每个图块覆盖的元素数量大致相同。里面的元素几乎覆盖了相同的范围。这表明,数字在表格中分布均匀。