45

I want to select all rows of a table followed by a random number between 1 to 9:

select t.*, (select dbms_random.value(1,9) num from dual) as RandomNumber
from myTable t

But the random number is the same from row to row, only different from each run of the query. How do I make the number different from row to row in the same execution?

1
  • Just to be clear, the dbms_random.value() call is only executed once, since the select it's in is evaluated before the outer select. Commented Oct 14, 2009 at 20:07

4 Answers 4

70

Something like?

select t.*, round(dbms_random.value() * 8) + 1 from foo t;

Edit: David has pointed out this gives uneven distribution for 1 and 9.

As he points out, the following gives a better distribution:

select t.*, floor(dbms_random.value(1, 10)) from foo t;
Sign up to request clarification or add additional context in comments.

3 Comments

The dbms_random.value(1,9) syntax is still correct. It's just the subquery structure that's wrong
Ah, not an even distribution of values though.
Thanks David. I think switching to trunc may give a better distribution
21

At first I thought that this would work:

select DBMS_Random.Value(1,9) output
from   ...

However, this does not generate an even distribution of output values:

select output,
       count(*)
from   (
       select round(dbms_random.value(1,9)) output
       from   dual
       connect by level <= 1000000)
group by output
order by 1

1   62423
2   125302
3   125038
4   125207
5   124892
6   124235
7   124832
8   125514
9   62557

The reasons are pretty obvious I think.

I'd suggest using something like:

floor(dbms_random.value(1,10))

Hence:

select output,
       count(*)
from   (
       select floor(dbms_random.value(1,10)) output
       from   dual
       connect by level <= 1000000)
group by output
order by 1

1   111038
2   110912
3   111155
4   111125
5   111084
6   111328
7   110873
8   111532
9   110953

1 Comment

dbms_random.value(1, 10) is probably more correct as the result x is greater than or equal to the first argument and less than the second according to the 10.2 docs
7

you don’t need a select … from dual, just write:

SELECT t.*, dbms_random.value(1,9) RandomNumber
  FROM myTable t

2 Comments

Ah, great. And how do I generate random integers from 1 to 9 instead of floating ?
use round … aaah, too late :(
6

If you just use round then the two end numbers (1 and 9) will occur less frequently, to get an even distribution of integers between 1 and 9 then:

SELECT MOD(Round(DBMS_RANDOM.Value(1, 99)), 9) + 1 FROM DUAL

1 Comment

An easier way to get an even distribution is to use floor

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.