SQL - 在 X 个表中平均分配相同的值

SQL - Distribute Same Values equally across X number of tables

我想看看是否有人知道在 "x" 个临时 table 中均匀分布多个相似值的方法,确保 'like' 值(此团队名称相同例如)永远不要被归为一个特定的 table。我想做的是为一场比赛制造热度,并在 table 之间平均分配队伍。例如:

**Teams**
-----------
Los Angeles
New York
New York
Los Angeles
Florida
Florida
Arizona
Texas
Alabama
Alaska
New York
New York
New York

我希望分配最终是这样的,所有多支球队平均分配到 2(或 3 或 4)场比赛中:

**Heat One**  
-------------                        
Los Angeles                       
New York                          
Florida                           
Arizona                           
Alabama                           
New York                          
New York

**Heat Two**
------------
Los Angeles
New York
Florida
Texas
Alaska
New York

这种方法听起来不对(有单独的表称为 Heat1、Heat2 等)所以您可能想重新考虑您在做什么,但如果您的情况决定这是一个好方法,那么如何分配每个团队的随机唯一(但连续)编号然后使用 MOD 将团队分开进行?为了让 'like' 队(相同的队名)进入不同的预赛,他们只需要随机在一起,MOD 将他们分开。

create table dbo.Teams (TeamId int, TeamName varchar(32))
go

insert dbo.Teams values
( 1, 'Los Angeles'),
( 2, 'New York'),
( 3, 'New York'),
( 4, 'Los Angeles'),
( 5, 'Florida'),
( 6, 'Florida'),
( 7, 'Arizona'),
( 8, 'Texas'),
( 9, 'Alabama'),
(10, 'Alaska'),
(11, 'New York'),
(12, 'New York'),
(13, 'New York')
go

-- First get a random number per unique team name
; with cte as (
    select row_number() over (order by newid()) as lrn, t.TeamName
    from dbo.Teams t
    group by t.TeamName     
)
-- Second get a unique random number per team with like teams ordered together
select row_number() over (order by lrn, newid()) - 1 as rn, t.*
into #teams
from dbo.Teams t
    join cte c on c.TeamName = t.TeamName

select 'Heat1', * 
from #teams 
where rn % 4 = 0

select 'Heat2', * 
from #teams 
where rn % 4 = 1

select 'Heat3', * 
from #teams 
where rn % 4 = 2

select 'Heat4', * 
from #teams 
where rn % 4 = 3

从 SQL Server 2005 开始,有一个用于存储数据的本机功能。 NTILE()

NTILE 函数是 SQL Server 2005 中引入的四个 windowing 函数中的第四个。NTILE 采用不同的方法对数据进行分区。 ROW_NUMBER、RANK 和 DENSE_RANK 将根据分区键生成可变大小的数据桶。 NTILE 尝试将数据分成相等的、固定大小的桶。 BOL 有一个综合页面比较排名功能,如果 你想要一个关于它们效果的快速视觉参考。

语法

NTILE 的语法与其他 window 函数略有不同。它是 NTILE(@BUCKET_COUNT) OVER ([PARTITION BY _] ORDER BY _) ,其中 @BUCKET_COUNT 是正整数或 bigint 值。

挑战在于确保我们获得良好的分布,这是受随机数生成器模糊影响的部分(newid 调用/(SELECT NULL))。

利用 Rhys 的设置

CREATE table dbo.Teams (TeamId int, TeamName varchar(32));

insert dbo.Teams values
( 1, 'Los Angeles'),
( 2, 'New York'),
( 3, 'New York'),
( 4, 'Los Angeles'),
( 5, 'Florida'),
( 6, 'Florida'),
( 7, 'Arizona'),
( 8, 'Texas'),
( 9, 'Alabama'),
(10, 'Alaska'),
(11, 'New York'),
(12, 'New York'),
(13, 'New York');

SELECT
    NTILE(2) OVER (ORDER BY NEWID()) AS Heat
,   NTILE(2) OVER (ORDER BY (SELECT NULL)) AS HeatAlternate
,   T.TeamName
,   T.TeamId
FROM
    dbo.Teams AS T
ORDER BY
    1,3;

这种方法的一个好处是,它可以通过简单地更改传递给 ntile 的值来切换成您想要的任何分桶大小。它还应该更好地扩展,因为它只需要一次通过源 table.