Pergunta

Estou tentando montar um sistema simples para um usuário gerar uma lista de usuários para quem as pesquisas serão enviadas. A geração da lista pode depender de várias restrições. Por exemplo, "queremos apenas pessoas dos EUA e do Canadá" ou "Queremos apenas pessoas que tenham uma associação de nível 2 ou 3".

Esta parte é bem fácil e eu configurei as tabelas para capturar os critérios de seleção. Um critério adicional, porém, é que eles podem querer obter uma certa porcentagem de cada item. Por exemplo, "Dê -me 70% dos usuários dos EUA e 30% dos usuários do Canadá". Novamente, acho que posso fazer isso sem muitos problemas. Eles darão o número de usuários que desejam, para que eu possa apenas várias porcentagens, e certifique -se de que os números ainda aumentem após o arredondamento e estou pronto para ir.

Pensando no futuro, e se eles quisessem certas falhas percentuais em dois conjuntos de critérios. Por exemplo, "Dê -me 70% dos EUA, 30% do Canadá e, ao mesmo tempo, usuários de 50% de nível 2 e 50% de usuários de nível 3". Como não é um requisito atual, não estou planejando me dar dor de cabeça sobre isso, mas se alguém tiver um algoritmo razoavelmente simples (ou código SQL) para realizar algo assim, ficaria feliz em vê -lo.

Embora eu prefira uma solução agnóstica de DB, estou no MS SQL 2005, portanto, as soluções específicas para que o RDBMS também estão bem.

A estrutura da tabela que estou usando atualmente é semelhante a isso:

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)
)
Foi útil?

Solução

Você pode dividir o problema em quatro conjuntos de usuários aleatórios:

  • Usuários dos EUA, nível 2, escolha 35% da amostra total desejada
  • Usuários do Canadá, nível 2, escolha 15% da amostra total desejada
  • Usuários dos EUA, nível 3, escolhem 35% da amostra total desejada
  • Usuários do Canadá, nível 3, escolhem 15% da amostra total desejada

Se houver um terceiro critério, divida o problema em oito conjuntos. E assim por diante.

Pode parecer artificial conseguir exatamente 50% Nível 2 e 50% Nível 3 em Ambas Conjuntos de usuários, EUA e Canadá. Como deveria ser aleatório, você pode esperar que varie um pouco mais. Além disso, e se não houver muitos usuários de nível 3 do Canadá para representar 15% do total?

À medida que os critérios ficam cada vez mais seletivos, você está naturalmente tirando a aleatoriedade da amostra total. Eventualmente, você pode ter uma longa lista de critérios, de modo que apenas um subconjunto de seus usuários pudesse satisfazê -lo e, em seguida, não haveria aleatoriedade.


Re seu comentário: Certo, o SQL não é a melhor solução para todo tipo de problema. Você pode ser melhor lidar com o problema com um iterativo Algoritmo em vez de uma única consulta SQL baseada em conjunto. Por exemplo:

  1. Escolha uma linha aleatória.
  2. Se a linha já foi escolhida em uma iteração anterior, descarte -a.
  3. Se a linha ajudar a manter o ritmo da escolha de uma amostra total de 70% dos EUA, 30% no Canadá, 50% de nível 2, 50% de nível 3, mantenha -o. Caso contrário, descarte -o.
  4. Se você atingir o número desejado de amostras, pare.
  5. Volte para a etapa 1.

Obviamente, fica complicado se você escolher uma linha que ajude a equilibrar a proporção de 70/30% das nações, mas desequilibra a proporção de 50/50% dos níveis. Você descarta ou não? E também pode ignorar os índices quando escolher apenas as primeiras linhas.

Como @Hogan comentou, esse pode ser um problema de NP-completo insolúvel. Mas muitos desses problemas têm uma solução que oferece um resultado "bom o suficiente", embora não seja um resultado comprovadamente ideal.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top