代码之家  ›  专栏  ›  技术社区  ›  Tom H

按百分比细分多个组时的随机选择

  •  1
  • Tom H  · 技术社区  · 14 年前

    我正试图建立一个简单的系统,让用户生成一个将向其发送调查的用户列表。列表生成可能依赖于各种约束。例如,“我们只想要来自美国和加拿大的人”或“我们只想要拥有2级或3级会员资格的人”。

    这部分非常简单,我已经设置了表来捕获选择条件。不过,另一个标准是,他们可能希望获得每个项目的特定百分比。例如,“给我70%的美国用户和30%的加拿大用户。”我再次认为我可以做到这一点而不需要太多麻烦。他们会给出他们想要的用户数量,所以我可以用百分比乘以,然后确保在四舍五入后这些数字仍然是加起来的,我很乐意去。

    不过,考虑到未来,如果他们希望按两套标准进行一定比例的细分,那该怎么办呢?例如,“给我70%的美国用户,30%的加拿大用户,同时给50%的二级用户和50%的三级用户。”因为这不是当前的要求,我不打算让自己为此感到头疼,但是如果有人有一个相当简单的算法(或SQL代码)来完成这样的事情,那么我会很高兴看到它。

    虽然我更喜欢数据库不可知的解决方案,但我使用的是MS SQL 2005,因此针对该RDBMS的解决方案也很好。

    我当前使用的表结构与此类似:

    CREATE TABLE Selection_Templates
    (
         template_code     VARCHAR(20)     NOT NULL,
         template_name     VARCHAR(100)    NOT NULL,
         CONSTRAINT PK_Selection_Templates PRIMARY KEY CLUSTERED (template_code),
         CONSTRAINT UI_Selection_Templates UNIQUE (template_name)
    )
    GO
    CREATE TABLE Selection_Template_Countries
    (
         template_code            VARCHAR(20)       NOT NULL,
         country_code             CHAR(3)           NOT NULL,
         selection_percentage     DECIMAL(2, 2)     NULL,
         CONSTRAINT PK_Selection_Template_Countries PRIMARY KEY CLUSTERED (template_code, country_code),
         CONSTRAINT CK_Selection_Template_Countries_selection_percentage CHECK (selection_percentage > 0),
         CONSTRAINT FK_Selection_Template_Countries_Selection_Template FOREIGN KEY (template_code) REFERENCES Selection_Templates (template_code)
    )
    GO
    CREATE TABLE Selection_Template_User_Levels
    (
         template_code            VARCHAR(20)       NOT NULL,
         user_level               SMALLINT          NOT NULL,
         selection_percentage     DECIMAL(2, 2)     NULL,
         CONSTRAINT PK_Selection_Template_User_Levels PRIMARY KEY CLUSTERED (template_code, user_level),
         CONSTRAINT CK_Selection_Template_User_Levels_selection_percentage CHECK (selection_percentage > 0),
         CONSTRAINT FK_Selection_Template_User_Levels_Selection_Template FOREIGN KEY (template_code) REFERENCES Selection_Templates (template_code)
    )
    
    1 回复  |  直到 14 年前
        1
  •  2
  •   Bill Karwin    14 年前

    您可以将问题分解为四组随机用户:

    • 美国用户,2级,选择所需总样本的35%
    • 加拿大用户,2级,选择所需总样本的15%
    • 美国用户,3级,选择所需总样本的35%
    • 加拿大用户,3级,选择所需总样本的15%

    如果有第三个标准,把问题分成八组。等等。

    可能是人为的 确切地 50%2级和50%3级 二者都 一组用户,美国和加拿大。因为它应该是随机的,所以您可能会期望它会有更多的变化。另外,如果加拿大的三级用户不多,占总数的15%怎么办?

    随着标准变得越来越有选择性,你自然就摆脱了总样本的随机性。最终,你可以有一长串的标准,这样你的用户中只有一个子集可以满足它,然后就没有随机性了。


    回复你的意见:对,对于每种类型的问题,SQL并不是最好的解决方案。你最好用一个 迭代的 算法而不是基于单一集合的SQL查询。例如:

    1. 选择一个随机行。
    2. 如果在上一次迭代中已经选择了该行,则放弃该行。
    3. 如果该行有助于保持选择70%美国、30%加拿大、50%二级、50%三级样本的速度,请保留该行。否则,丢弃它。
    4. 如果达到所需的样本数量,请停止。
    5. 回到步骤1。

    当然,如果你选择一个有助于平衡70/30%的国家比例,但不平衡50/50%的水平比例的行,就会变得很棘手。你是否丢弃它?另外,当您只选择了前几行时,您可能希望忽略这些比率。

    正如@hogan评论的那样,这可能是一个无法解决的NP完全问题。但是很多这样的问题都有一个解决方案,它会给你一个“足够好”的结果,尽管不是一个可以证明的最佳结果。