In MySQL I can use the RAND() function, is there any alternative in SQLite 3?
using random():
SELECT foo FROM bar
WHERE id >= (abs(random()) % (SELECT max(id) FROM bar))
LIMIT 1;
EDIT (by QOP): Since the docs on SQLite Autoincremented columns states that:
The normal ROWID selection algorithm described above will generate monotonically increasing unique ROWIDs as long as you never use the maximum ROWID value and you never delete the entry in the table with the largest ROWID. If you ever delete rows, then ROWIDs from previously deleted rows might be reused when creating new rows.
The above is only true if you don't have a INTEGER PRIMARY KEY AUTOINCREMENT
column (it will still work fine with INTEGER PRIMARY KEY
columns). Anyway, this should be more portable / reliable:
SELECT foo FROM bar
WHERE _ROWID_ >= (abs(random()) % (SELECT max(_ROWID_) FROM bar))
LIMIT 1;
ROWID
, _ROWID_
and OID
are all aliases for the SQLite internal row id.
SELECT * FROM table ORDER BY RANDOM() LIMIT 1;
using random():
SELECT foo FROM bar
WHERE id >= (abs(random()) % (SELECT max(id) FROM bar))
LIMIT 1;
EDIT (by QOP): Since the docs on SQLite Autoincremented columns states that:
The normal ROWID selection algorithm described above will generate monotonically increasing unique ROWIDs as long as you never use the maximum ROWID value and you never delete the entry in the table with the largest ROWID. If you ever delete rows, then ROWIDs from previously deleted rows might be reused when creating new rows.
The above is only true if you don't have a INTEGER PRIMARY KEY AUTOINCREMENT
column (it will still work fine with INTEGER PRIMARY KEY
columns). Anyway, this should be more portable / reliable:
SELECT foo FROM bar
WHERE _ROWID_ >= (abs(random()) % (SELECT max(_ROWID_) FROM bar))
LIMIT 1;
ROWID
, _ROWID_
and OID
are all aliases for the SQLite internal row id.
Solved:
SELECT * FROM table ORDER BY RANDOM() LIMIT 1;
For a much better performance use this in SQLite:
SELECT * FROM table WHERE id IN (SELECT id FROM table ORDER BY RANDOM() LIMIT x)
This is also applicable to MySQL. This runs faster because SQL engines first load projected fields of rows to memory then sort them, here we just load and random sort the id field of rows, then we get X of them, and find the whole rows of these X ids which is by default indexed.
SELECT * FROM table ORDER BY RANDOM() LIMIT 1
, and still gives true random w/o any requirements to table schema. –
Carrasco The goal is to get random results (Infinite Scroll) while being able to SQL paginate the results (LIMIT a,b
), which needs a predictible outcome (pseudorandom aka PRNG).
SIN(id + seed)
seems a great alternative to RANDOM(seed)
.
Please consider this demo entirely written in JS that simulates an ORDER BY
clause using a SIN(id + seed)
scoring :
// Inspired by:
// https://www.sqlite.org/forum/forumpost/e2216583a4
// https://mcmap.net/q/49600/-order-by-random-with-seed-in-sqlite
// Simulate N autoincrement stable ids
// (Avoid rowid which is unstable)
const max = 20;
const a = Array();
for (let id = 0; id < max; ++id) {
a.push({id});
}
console.log(a);
// Order the results by random
const orderByRandom = ({a, seed}) => {
// For each result,
// Use sin(id + seed) to get a stable random score
const randomScored = a.map(x => {
return { ...x, score: Math.sin(x.id + seed) }
});
// Sort by the random score
randomScored.sort((a,b) => a.score - b.score);
return randomScored;
}
// Used for generating the seed
const random = () => 1 + Math.floor(Math.random() * Number.MAX_SAFE_INTEGER - 1);
let seed;
seed = random(); // seed #1
console.log(orderByRandom({a, seed}));
console.log(orderByRandom({a, seed})); // Stable, can paginate
seed = random(); // seed #2
console.log(orderByRandom({a, seed})); // New order because new seed
© 2022 - 2024 — McMap. All rights reserved.