【问题标题】:SQL Server : how to divide database records into even, random groupsSQL Server:如何将数据库记录分成偶数、随机组
【发布时间】:2017-09-18 20:58:48
【问题描述】:

tblNames

  • 组织 ID(整数)
  • 姓氏(varchar)
  • ...
  • 组号(整数)

GroupNumber 当前对所有记录都为 NULL,我需要一个 UPDATE 语句来更新此列。

我需要将OrganizationID 级别的记录分成偶数、随机组。

如果OrganizationID 的记录少于 20,000 条,我需要 2 个偶数随机组。因此,OrganizationID 的记录将具有 1 或 2 的 GroupNumberGroupNumber = 1GroupNumber = 2 的记录数将相同(或者如果奇数记录差异仅为 1),并且有将无法识别一个人如何进入 GroupNumber - 即以 A-L 开头的姓氏是第 1 组,M-Z 是第 2 组是不行的。

如果OrganizationID 有 > 20,000 条记录,我需要 4 个偶数随机组。因此,OrganizationID 的记录将具有 GroupNumber 值 1、2、3 或 4。每个 GroupNumber 的记录数将相同(或者如果奇数记录差异仅为 1),并且没有可识别的方式来判断一个人是如何进入 GroupNumber 的 - 即,以 A-F 开头的姓氏是第 1 组,G-L 是第 2 组,等等。

只有大约 20 个组织,所以我可以运行 20 次更新语句,如果需要,每个 organizationID 一次。

我可以完全控制表格,所以我可以添加键或列,但现在就是这样。

不胜感激。

【问题讨论】:

  • MSSQL 的外行,但是您不能获取 ID,以您选择的语言对其进行洗牌,并对结果数组的部分进行 n 更新查询,其中 n 是组数?跨度>
  • 我什至看不懂你的问题

标签: sql-server random


【解决方案1】:

随机创建行号(使用ROW_NUMBERGETID)。然后根据记录数获取它们的模 2 或 4,以获得 0 到 1 或 0 到 3 的存储桶。

select 
  organizationid, lastname, ...,
  case when cnt <= 20000 then rn % 2 else rn % 4 end as bucket
from
(
  select 
    organizationid, lastname, ...,
    row_number() over(order by newid()) as rn,
    count(*) over () as cnt
  from mytable
) randomized;

更新:我想更新语句应该是这样的:

with randomized as
(
  select 
    groupnumber,
    row_number() over(order by newid()) as rn,
    count(*) over () as cnt
  from mytable
)
update randomzized
set groupnumber = case when cnt <= 20000 then rn % 2 else rn % 4 end + 1;

【讨论】:

    【解决方案2】:

    另一种略有不同的方法;

    设置一些假数据:

    if object_id('tempdb.dbo.#Orgs') is not null drop table #Orgs
    create table #Orgs
    (
        RID int identity(1,1) primary key clustered,
        OrganizationId int,
        LastName varchar(36),
        GroupId int
    )
    
    insert into #Orgs (OrganizationId, LastName)
    select top 40000 row_number() over (order by (select null)) % 20000, newid()
    from sys.all_objects a, sys.all_objects b
    

    然后使用很少有用的ntile() 函数来尽可能接近相同大小的组。按newid() 排序本质上是对数据进行随机排序(或者与生成下一个 guid 一样随机)。

    declare @NumRandomGroups int = 4
    
    update o
    set GroupId = x.GroupId 
    from #orgs o 
    inner join (select RID, GroupId = ntile(@NumRandomGroups) over (order by newid())
                from #orgs) x 
        on o.RID = x.RID
    
    select GroupId, count(1)
    from #Orgs
    group by GroupId
    
    select *
    from #Orgs
    order by RID
    

    然后您可以根据组织的数量将@NumRandomGroups 设置为您想要的任何值

    【讨论】:

    • ntile! 这就是我之前读到这篇文章时想要记住的:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 2011-08-18
    相关资源
    最近更新 更多