Tmb wrote:
> I created a SQLite database where a table 'names' is located. This table
> stores just a single column called 'name'. Now I tried for test purposes to
> create a random number within range [0..1] for each record in the table
> using a SELECT statement like this:
> 
> select name, (random() / 9223372036854775807.0 + 1.0) / 2.0 as RNDValue from
> names;
> 
> This works fine and the random values are successfully generated within the
> required range. Now, I tried to select just a subset of records with a
> random value >= 0.99 for example (using a WHERE condition).
> 
> The query looks now like:
> 
> select name, (random() / 9223372036854775807.0 + 1.0) / 2.0 as RNDValue from
> names where RNDValue >= 0.99;
> 
> The query returns just a few records, which is fine - but the problem is,
> that RNDValues less than 0.99 are returned.
> 
> If I execute the above mentioned query, I get a result like this:
> 
> Name   RNDValue
> Name1  0.23...
> Name2  0.521...
> Name3  0.429...
> Name4  0.725...
> Name5  0.149...
> 
> Is this an error within SQLite or am I just misunderstanding it?
> 
> Thank you for your suggestions/comments.

The problem you are seeing is due to the fact that SQLite substitutes 
the expression for RNDValue into the where clause, not the value. You 
can see this if you do an explain.

SQLite version 3.6.1
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table names(name text);
sqlite> .explain on
sqlite> explain select name, (random() / 9223372036854775807.0 + 1.0) / 
2.0 as R
NDValue from
    ...> names where RNDValue >= 0.99;
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Trace          0     0     0     explain select name, (random() / 
92233720
36854775807.0 + 1.0) / 2.0 as RNDValue from
names where RNDValue >= 0.99;  00
1     Real           0     1     0     9.223372036854778e+18  00
2     Real           0     2     0     1              00
3     Real           0     3     0     2              00
4     Real           0     4     0     0.99           00
5     Goto           0     26    0                    00
6     SetNumColumns  0     1     0                    00
7     OpenRead       0     2     0                    00
8     Rewind         0     24    0                    00
9     Function       0     0     8     random(-1)     00
10    Divide         1     8     7                    00
11    Add            2     7     6                    00
12    Divide         3     6     5                    00
13    Lt             4     23    5                    6a
14    Column         0     0     10                   00
15    Function       0     0     7     random(-1)     00
16    Real           0     8     0     9.223372036854778e+18  00
17    Divide         8     7     6                    00
18    Real           0     8     0     1              00
19    Add            8     6     5                    00
20    Real           0     8     0     2              00
21    Divide         8     5     11                   00
22    ResultRow      10    2     0                    00
23    Next           0     9     0                    00
24    Close          0     0     0                    00
25    Halt           0     0     0                    00
26    Transaction    0     0     0                    00
27    VerifyCookie   0     1     0                    00
28    TableLock      0     2     0     names          00
29    Goto           0     6     0                    00
sqlite>

There are two calls to the random function, one is used in the where 
clause, the other is used to calculate the value to put in the result row.

Igor suggested using a subselect,but that has the same issue.

sqlite> explain select name, RNDValue
    ...> from (
    ...>     select name, (random() / 9223372036854775807.0 + 1.0) / 2.0 as
    ...> RNDValue from names
    ...> )
    ...> where RNDValue >= 0.99;
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Trace          0     0     0     explain select name, RNDValue
from (
     select name, (random() / 9223372036854775807.0 + 1.0) / 2.0 as
RNDValue from names
)
where RNDValue >= 0.99;  00
1     Real           0     1     0     9.223372036854778e+18  00
2     Real           0     2     0     1              00
3     Real           0     3     0     2              00
4     Real           0     4     0     0.99           00
5     Goto           0     26    0                    00
6     SetNumColumns  0     1     0                    00
7     OpenRead       1     2     0                    00
8     Rewind         1     24    0                    00
9     Function       0     0     8     random(-1)     00
10    Divide         1     8     7                    00
11    Add            2     7     6                    00
12    Divide         3     6     5                    00
13    Lt             4     23    5     collseq(BINARY)  6a
14    Column         1     0     10                   00
15    Function       0     0     7     random(-1)     00
16    Real           0     8     0     9.223372036854778e+18  00
17    Divide         8     7     6                    00
18    Real           0     8     0     1              00
19    Add            8     6     5                    00
20    Real           0     8     0     2              00
21    Divide         8     5     11                   00
22    ResultRow      10    2     0                    00
23    Next           1     9     0                    00
24    Close          1     0     0                    00
25    Halt           0     0     0                    00
26    Transaction    0     0     0                    00
27    VerifyCookie   0     1     0                    00
28    TableLock      0     2     0     names          00
29    Goto           0     6     0                    00
sqlite>

You could try this instead.

-- create temp table with random numbers
create temp table rnd(id integer primary key, RNDValue real);
insert into rnd
     select rowid, (random() / 9223372036854775807.0 + 1.0) / 2.0 as 
RNDValue from names;

-- select name based on associated random numbers
select name, RNDValue
from names
join rnd on names.rowid = rnd.id
where rnd.RNDValue < 0.99;

-- delete temp table
drop table rnd;

HTH
Dennis Cote
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to