Gerar valor interno aleatório de 3 a 6

101

É possível no Microsoft SQL Server gerar um valor interno aleatório de Min a Max (3-9 exemplo, 15-99 etc)

Eu sei, posso gerar de 0 a Max, mas como aumentar a borda Min?

Esta consulta gera um valor aleatório de 1 a 6. É necessário alterá-lo de 3 para 6.

SELECT table_name, 1.0 + floor(6 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables

Adicionado 5 segundos depois :

Pergunta estúpida, desculpe ...

SELECT table_name, 3.0 + floor(4 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables
FSou1
fonte
1
A resposta que você tem lá só funciona se você tiver permissões de tipo de administrador na mesa. A maneira de contornar isso foi usando a chave primária no campo como a semente. A distribuição não foi brilhante, mas serviu ao propósito.
Shadow

Respostas:

196

Isso gera um número aleatório entre 0-9

SELECT ABS(CHECKSUM(NEWID()) % 10)

1 a 6

SELECT ABS(CHECKSUM(NEWID()) % 6) + 1

3 a 6

SELECT ABS(CHECKSUM(NEWID()) % 4) + 3

Dinâmico (baseado no comentário de Eilert Hjelmeseths)

SELECT ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min

Atualizado com base em comentários:

  • NEWID gera string aleatória (para cada linha de retorno)
  • CHECKSUM pega o valor da string e cria o número
  • modulus ( %) divide por esse número e retorna o resto (o que significa que o valor máximo é um a menos do que o número que você usa)
  • ABS muda os resultados negativos para positivos
  • em seguida, adicione um ao resultado para eliminar 0 resultados (para simular um lançamento de dados)
orgtigger
fonte
2
isso me ajudou muito! apenas lembre-se de que se você está tentando gerar chaves aleatórias para inserções em massa, isso pode causar duplicatas e algumas instruções falharão. mas obrigada!
Niklas
3
E se eu tiver que gerar um número aleatório entre 1 e 27? ou seja, faixa maior que 9?
somegeek
4
Se eu estiver seguindo a lógica, parece que esse ajuste permitirá que você defina o intervalo de forma precisa e dinâmica, facilmente. ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min. Alguns testes da minha parte produziram bons resultados. Se for realmente preciso, acho que essa resposta poderia ser ligeiramente melhorada incluindo-a.
Eilert Hjelmeseth
13

Vejo que você adicionou uma resposta à sua pergunta no SQL Server 2008, você também pode fazer

SELECT 3 + CRYPT_GEN_RANDOM(1) % 4 /*Random number between 3 and 6*/ 
FROM ...

Algumas desvantagens deste método são

  1. Isso é mais lento do que o NEWID()método
  2. Mesmo que seja avaliado uma vez por linha, o otimizador de consulta não percebe isso, o que pode levar a resultados estranhos .

mas apenas pensei em adicioná-lo como outra opção.

Martin Smith
fonte
1
@ FSou1 - Sim. Acho que CRYPT_GEN_RANDOMé realmente destinado a situações em que você precisa de um número pseudoaleatório mais criptograficamente seguro.
Martin Smith
7

Você consegue fazer isso:

DECLARE @maxval TINYINT, @minval TINYINT
select @maxval=24,@minval=5

SELECT CAST(((@maxval + 1) - @minval) *
    RAND(CHECKSUM(NEWID())) + @minval AS TINYINT)

E isso foi tirado diretamente deste link , eu realmente não sei como dar o devido crédito a esta resposta.

Lamak
fonte
5

Bom e simples, do site de Pinal Dave:

http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/

DECLARE @Random INT;
DECLARE @Upper INT;
DECLARE @Lower INT
SET @Lower = 3 ---- The lowest random number
SET @Upper = 7 ---- One more than the highest random number
SELECT @Random = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
SELECT @Random

(Eu fiz uma ligeira alteração em @ Upper- para incluir o número superior, acrescentei 1.)

Adrian Carr
fonte
Eu vi esse exemplo em outra postagem. Não fornece uma distribuição aleatória. Por exemplo, Lower é 1 e Upper é 11, então eu quero números aleatórios de 1 a 10. O 1 e o 10 obtêm metade das ocorrências como 2-8. Vá e teste.
nanonerd
4

Simplesmente:

DECLARE @MIN INT=3; --We define minimum value, it can be generated.
DECLARE @MAX INT=6; --We define maximum value, it can be generated.

SELECT @MIN+FLOOR((@MAX-@MIN+1)*RAND(CONVERT(VARBINARY,NEWID()))); --And then this T-SQL snippet generates an integer between minimum and maximum integer values.

Você pode alterar e editar este código de acordo com suas necessidades.

MERT DOĞAN
fonte
1
Embora este trecho de código seja bem-vindo e possa fornecer alguma ajuda, seria muito melhor se incluísse uma explicação de como aborda a questão. Sem isso, sua resposta tem muito menos valor educacional - lembre-se de que você está respondendo a pergunta para os leitores no futuro, não apenas para a pessoa que está perguntando agora! Por favor edite sua resposta para adicionar explicação, e dar uma indicação do que limitações e premissas se aplicam.
Toby Speight
4

Aqui está a linha de código simples e única

Para isso, use a função SQL Inbuild RAND () .

Aqui está a fórmula para gerar um número aleatório entre dois números (RETURN INT Range)

Aqui, a é o seu primeiro número (mínimo) eb é o segundo número (máximo) no intervalo

SELECT FLOOR(RAND()*(b-a)+a)

Nota: Você também pode usar a função CAST ou CONVERT para obter o número do intervalo INT.

(CAST (RAND () * (25-10) +10 AS INT))

Exemplo:

SELECT FLOOR(RAND()*(25-10)+10);

Aqui está a fórmula para gerar um número aleatório entre dois números (RETURN DECIMAL Range)

SELECT RAND()*(b-a)+a;

Exemplo:

SELECT RAND()*(25-10)+10;

Mais detalhes verifique isto: https://www.techonthenet.com/sql_server/functions/rand.php

Manjunath Bilwar
fonte
1
Observe que, conforme mencionado no artigo vinculado, isso não irá gerar valores = máx. Para fazer isso, por exemplo, para valores> = 10 e <= 25, você precisaria de SELECT FLOOR (RAND () * (25-10 + 1)) + 10
Shaun
1
SELECT ROUND((6 - 3 * RAND()), 0)
greg121
fonte
2
A chance de obter um número sobre o outro não é distribuída igualmente. Verifique a saída disso: SELECT ROUND((6 - 3 * 0.16), 0) SELECT ROUND((6 - 3 * 0.17), 0) SELECT ROUND((6 - 3 * 0.5), 0) SELECT ROUND((6 - 3 * 0.51), 0) SELECT ROUND((6 - 3 * 0.83), 0) SELECT ROUND((6 - 3 * 0.84), 0) Mostra que 16% de mudança para 6, ~ 34% é 5, ~ 34% é 4 e ~ 16% é 3.
Mike de Klerk
truncar é superior ao arredondamento
MichaelChirico
0

A resposta de Lamak como uma função:

-- Create RANDBETWEEN function
-- Usage: SELECT dbo.RANDBETWEEN(0,9,RAND(CHECKSUM(NEWID())))
CREATE FUNCTION dbo.RANDBETWEEN(@minval TINYINT, @maxval TINYINT, @random NUMERIC(18,10))
RETURNS TINYINT
AS
BEGIN
  RETURN (SELECT CAST(((@maxval + 1) - @minval) * @random + @minval AS TINYINT))
END
GO
AndreFeijo
fonte
0
DECLARE @min INT = 3;
DECLARE @max INT = 6;
SELECT @min + ROUND(RAND() * (@max - @min), 0);

Passo a passo

DECLARE @min INT = 3;
DECLARE @max INT = 6;

DECLARE @rand DECIMAL(19,4) = RAND();
DECLARE @difference INT = @max - @min;
DECLARE @chunk INT = ROUND(@rand * @difference, 0);
DECLARE @result INT = @min + @chunk; 
SELECT @result;

Observe que uma função definida pelo usuário não permite o uso de RAND (). Uma solução alternativa para isso (fonte: http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/ ) é criar primeiro uma visualização.

CREATE VIEW [dbo].[vw_RandomSeed]
AS
SELECT        RAND() AS seed

e então criar a função aleatória

CREATE FUNCTION udf_RandomNumberBetween
(
    @min INT,
    @max INT
)
RETURNS INT
AS
BEGIN
    RETURN @min + ROUND((SELECT TOP 1 seed FROM vw_RandomSeed) * (@max - @min), 0);
END
Mike de Klerk
fonte
0

Em geral:

select rand()*(@upper-@lower)+@lower;

Para sua pergunta:

select rand()*(6-3)+3;

<=>

select rand()*3+3;
Zeinab
fonte