Génère un nombre aléatoire compris entre 1 et 10

95

Comme mon approche pour une requête de test sur laquelle j'ai travaillé dans cette question n'a pas fonctionné, j'essaye autre chose maintenant. Existe-t-il un moyen de dire à la random()fonction de pg de ne me donner que des nombres entre 1 et 10?

KB22
la source

Réponses:

152

Si par des nombres entre 1 et 10 vous entendez n'importe quel flotteur qui est> = 1 et <10, alors c'est facile:

select random() * 9 + 1

Cela peut être facilement testé avec:

# select min(i), max(i) from (
    select random() * 9 + 1 as i from generate_series(1,1000000)
) q;
       min       |       max
-----------------+------------------
 1.0000083274208 | 9.99999571684748
(1 row)

Si vous voulez des entiers, qui sont> = 1 et <10, alors c'est simple:

select trunc(random() * 9 + 1)

Et encore une fois, test simple:

# select min(i), max(i) from (
    select trunc(random() * 9 + 1) as i from generate_series(1,1000000)
) q;
 min | max
-----+-----
   1 |   9
(1 row)
Klesun
la source
sélectionner la date (e.created_at) + (trunc (random () * 20)) à partir des événements e; résultat: ERREUR: l'opérateur n'existe pas: date + double précision Trunc renvoie-t-il vraiment des entiers?
Bogdan Gusiev
3
trunc()renvoie le même type de données que l'entrée (comme indiqué dans le manuel). Vous devez trunc(random() * 20)::int
convertir
Je me demande si au moins en théorie, il est possible que random()renvoie une valeur <1 qui, multipliée par 9, serait> = 9 en raison de la nature inexacte du type à double précision ? En pratique, même si cela est possible, ce serait bien sûr très improbable à cause des 15 chiffres environ.
1
Je joue avec width_bucket(random(), 0, 1, 10)comme alternative
Il semble que mes craintes étaient sans fondement même si j'avoue que je ne comprends pas du tout les mathématiques :-)
17

Pour résumer et simplifier un peu, vous pouvez utiliser:

-- 0 - 9
select floor(random() * 10);
-- 0 - 10
SELECT floor(random() * (10 + 1));
-- 1 - 10
SELECT ceil(random() * 10);

Et vous pouvez tester ceci comme mentionné par @ user80168

-- 0 - 9
SELECT min(i), max(i) FROM (SELECT floor(random() * 10) AS i FROM generate_series(0, 100000)) q;
-- 0 - 10
SELECT min(i), max(i) FROM (SELECT floor(random() * (10 + 1)) AS i FROM generate_series(0, 100000)) q;
-- 1 - 10
SELECT min(i), max(i) FROM (SELECT ceil(random() * 10) AS i FROM generate_series(0, 100000)) q;
qd3v
la source
2
La documentation dit "valeur aléatoire dans la gamme 0.0 <= x <1.0", donc il y a au moins une chance théorique de ceil(random() * 10)résulter en 0 - je m'en tiendrai floor.
1
Je suis d'accord avec @JackDouglas, donc pour la gamme 1 - 10 ça devrait êtreSELECT floor(random() * 10 + 1);
SergiyKolesnikov
9

Si vous utilisez SQL Server, la méthode correcte pour obtenir un entier est

SELECT Cast(RAND()*(b-a)+a as int);

  • 'b' est la limite supérieure
  • 'a' est la limite inférieure
Neha Jain
la source
Faites attention ici, si vous mettez votre limite inférieure à 1 et supérieure à 10, vous n'obtiendrez que les nombres 1-> 9. D'autres réponses semblent supposer qu'entre 1 et 10 signifie 1-> 9 ... Je suggérerais que si «entre» exclut la limite supérieure, il devrait également exclure la limite inférieure (c'est-à-dire 2-> 9). SELECT Cast (RAND () * ((b + 1) -a) + a comme int);
Morvael
La question est clairement identifiée comme une question PostgreSQL.
Sebastian Palma
4

(tronc (aléatoire () * 10)% 10) + 1

hythlodayr
la source
ERREUR: l'opérateur n'existe pas: double précision% integer
1
Et pourquoi utiliseriez-vous le module de toute façon? Cette logique n'a pas de sens. Si vous obtenez un "wrapping", vous n'aurez pas une distribution égale, et si vous n'en obtenez pas, vous n'en avez pas besoin.
ErikE
1

La version correcte de la réponse de hythlodayr.

-- ERROR:  operator does not exist: double precision % integer
-- LINE 1: select (trunc(random() * 10) % 10) + 1

La sortie de truncdoit être convertie en INTEGER. Mais cela peut se faire sans trunc. Cela s'avère donc simple.

select (random() * 9)::INTEGER + 1

Génère une sortie INTEGER dans la plage [1, 10], c'est-à-dire à la fois 1 et 10 inclus.

Pour tout nombre (flottants), voir la réponse de user80168. c'est-à-dire ne pas le convertir en INTEGER.

mythique codeur
la source
0

En fait, je ne sais pas que vous le voulez.

essaye ça

INSERT INTO my_table (my_column)
SELECT
    (random() * 10) + 1
;
leejaycoke
la source
0

Cette procédure stockée insère un nombre rand dans une table. Attention, il insère un nombre infini. Arrêtez de l'exécuter lorsque vous obtenez suffisamment de nombres.

créer une table pour le curseur:

CREATE TABLE [dbo].[SearchIndex](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Cursor] [nvarchar](255) NULL) 

ALLER

Créez un tableau pour contenir vos nombres:

CREATE TABLE [dbo].[ID](
[IDN] [int] IDENTITY(1,1) NOT NULL,
[ID] [int] NULL)

INSÉRER LE SCRIPT:

INSERT INTO [SearchIndex]([Cursor])  SELECT N'INSERT INTO ID  SELECT   FLOOR(rand() * 9 + 1)  SELECT COUNT (ID) FROM ID

CRÉATION ET EXÉCUTION DE LA PROCÉDURE:

CREATE PROCEDURE [dbo].[RandNumbers] AS
BEGIN
Declare  CURSE  CURSOR  FOR (SELECT  [Cursor] FROM [dbo].[SearchIndex]  WHERE [Cursor] IS NOT NULL)
DECLARE @RandNoSscript NVARCHAR (250)
OPEN CURSE
FETCH NEXT FROM CURSE
INTO @RandNoSscript 
WHILE @@FETCH_STATUS IS NOT NULL 
BEGIN
Print @RandNoSscript
EXEC SP_EXECUTESQL @RandNoSscript;  
 END
 END
GO

Remplissez votre table:

EXEC RandNumbers
Abu Khalil Mohamed
la source
3
La question concerne Postgres, pas SQL Server
a_horse_with_no_name