Limit by RAND without random order - mysql

I am trying to select records in order but limited randomly.
SELECT * FROM tm_winners WHERE paid_out=0 ORDER BY DESC LIMIT RAND(4,8)
However it seems I cannot have a random limit of rows. I am bassiclty trying to grab between 4 and 8 rows but NOT randomly, just limited randomly.

You'll have to use a prepared statement to use a variable amount in the LIMIT clause.
SET #lrand = FLOOR(4 + RAND() * (8 - 4));
PREPARE STMT FROM 'SELECT * tm_winners WHERE paid_out=0 ORDER BY DESC LIMIT ?';
EXECUTE STMT USING #lrand;

Personally, even if its not the cleanest way, Id set a var previous to the select statement and Limit by the var.
$randomVar = rand(4, 8);
$sql = 'SELECT * FROM tm_winners WHERE paid_out=0 ORDER BY DESC LIMIT 0,'.$randomVar;
Clearly if you wanted randomness within the actual results, you could clearly reintroduce the rand() within the statement
Hope it helps
Will

Related

How to create two tables with first 75% and remaining 25% of another table in MySQL?

I wrote this expecting it would work but LIMIT and OFFSET doesn't allow me do any calculations by giving error : "Error Code: 1327. Undeclared variable: ceil
"
INSERT INTO as24t
SELECT * FROM as24 LIMIT ceil(count(*)*3/4);
INSERT INTO as24v
SELECT * FROM as24 LIMIT floor(count(*)/4) OFFSET ceil(count(*)*3/4);
All I want to do is take first 3/4 of as24 table and insert into as24t and remaining 1/4 to as24v, considering some tables have odd number of records. Also, I don't want to calculate it and hardcode numbers into query because I have 40+ tables to divide and I feel there must be a clever way.
Please find something unique to order by in order to verify that you get complement sets.
set #numrows_25=(select count(*) from as24) * 0.25;
PREPARE STMT FROM 'INSERT INTO as24v SELECT * FROM as24 order by ... LIMIT ?';
EXECUTE STMT USING #numrows_25;
PREPARE STMT FROM 'INSERT INTO as24t SELECT * FROM as24 order by ... LIMIT 9999999999 OFFSET ?';
EXECUTE STMT USING #numrows_25;

Can I use MySQL functions in the LIMIT offset

Can I use MySQL functions in the LIMIT offset?
Like:
SELECT * FROM sites WHERE ... LIMIT FLOOR(1 + RAND() * (SELECT COUNT(*) FROM sites)) , 1
No, you can't do that directly. LIMIT and OFFSET values must be constants.
Citation from the MySQL docs:
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants (except when using prepared statements).
You can use prepared statements and variables, though:
SELECT #offset:=FLOOR(1 + RAND() * COUNT(*)) FROM sites;
PREPARE STMT FROM 'SELECT * FROM sites WHERE ... LIMIT ?, 1';
EXECUTE STMT USING #offset;

Issue with using MAX()

I was answering a question on SO that encountered this issue.
Why I can't use MAX() within a LIMIT?
SELECT *
FROM table
ORDER BY id DESC
LIMIT 0, MAX(id)
Or
SELECT *, MAX(id) AS m
FROM table
ORDER BY id DESC
LIMIT 0, m
Both give a similar syntax error:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MAX(id)' at line 4
Wanted query:
SELECT *
FROM table
ORDER BY id DESC
LIMIT 0, MAX(id)-5
MAX() is an aggregate function over the result rows, but LIMIT is a clause that constrains the number of result rows. In short, you cannot use a function that depends on the result rows while you are still determining which rows will be in the result -- that simply doesn't make any sense.
According to the documentation, LIMIT arguments must either be integer constants or parameters of a prepared query (emphasis mine):
LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants (except when using prepared statements).
The syntax specification simply does not allow a column or function to be used. You would have to pre-compute the value and then use it in a prepared query (or by string substitution, though I would avoid that).
Based on the query you gave in your question:
SELECT *
FROM table
ORDER BY id DESC
LIMIT 0, MAX(id)-5
I suspect that this is the query you actually want:
SELECT *
FROM table
WHERE id <= (SELECT MAX(id) FROM table) - 5
ORDER BY id DESC
Even if it were valid, the first query you gave will not do what you expect if there are gaps in the sequence of the id column (for example, if a row was deleted).
An alternative if you want to get your desired result is to create a dynamic sql.
SET #maxID = (SELECT MAX(ID) FROM tableName);
SET #sql = CONCAT('SELECT *
FROM tableName
ORDER BY ID DESC
LIMIT 0,', #maxID);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
The function MAX cannot be used on the limit.
Here is the documentation:
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_max
The count argument in the limit should be a value so you cannot execute that in one step. Here is the select documentation:
http://dev.mysql.com/doc/refman/5.0/en/select.html
You can do is:
SET #a=(SELECT MAX(ID) FROM table);
PREPARE STMT FROM 'SELECT * FROM table ORDER BY id DESC LIMIT 0, ?';
EXECUTE STMT USING #a;
So it is a tree step here. Get max in a variable. Prepare a statement and than execute it applying the variable to the statement.
You can use the HAVING clause with MAX(id) to obtain your desired result
SELECT *
FROM table1
HAVING id<((SELECT Max(id) FROM table1)-5)
ORDER BY id DESC
Fiddle http://sqlfiddle.com/#!2/16e50/3
ISSUE IS WIth your query::
Select
*
from
myTable,
(SELECT MAX(id) as n
FROM table) temp
ORDER BY id DESC
LIMIT 0, temp.n

mysql select inside limit

select
id
from
tableABC
limit (select count(id) from tableCBA), 1
If I need select in limit as I have shown here in sample code, how can I do this in mySql? This is only simplified code for purpose of this forum, otherwise this is a part of sophisticated case when else select.
You can't directly have a dynamic value for limit, but your query can be re-written without the limit, as follows:
set i := (select count(*) from tableCBA);
select id
from tableABC
where (i := i-1) = 0;
This will return the nth row, where n is the number of rows in tableCBA;
select #LimitRowsCount1=count(id) from tableCBA;
PREPARE STMT FROM "SELECT id from tableABC LIMIT ?";
EXECUTE STMT USING #LimitRowsCount1;

Fetching RAND() rows without ORDER BY RAND() in just one query

Using RAND() in MySQL to get a single random row out of a huge table is very slow:
SELECT quote FROM quotes ORDER BY RAND() LIMIT 1
Here is an article about this issue and why this is the case.
Their solution is to use two queries:
SELECT COUNT(*) AS cnt FROM quotes
- Use result to generate a number between 0 and COUNT(*)
SELECT quote FROM quotes LIMIT $generated_number, 1
I was wondering, whether this would be possible in just one query.
So my approach was:
SELECT * FROM quotes
LIMIT (
ROUND(
(SELECT COUNT(*) FROM quotes) * RAND()
)
), 1
But it seams MySQL does not allow any logic within Limit.
Though I can not find any information about this topic, whether this is true.
So my Questions:
How can I use RAND() within LIMIT?
Do you know of any other way to
solve this with just one query?
Is there a reason why a stored procedure cannot be used to create a prepared statement?
DELIMITER //
DROP PROCEDURE IF EXISTS rand_quote//
CREATE PROCEDURE rand_quote()
BEGIN
SET #rand := ROUND((SELECT COUNT(*) FROM quotes) * RAND());
SET #sql := CONCAT('SELECT * FROM quotes LIMIT ', #rand, ', 1');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
//
DELIMITER ;
I just figgured this one, that seams like a solution:
SELECT * FROM quotes
WHERE quotes_id = ROUND(
(SELECT COUNT(*) FROM quotes) * RAND()
)
LIMIT 1
But it will work only if quotes_id has no gaps.
I solved the problem by checking max id. Then i made php loop of rand(0, max_id) which checks if object exists. Done.
Much faster then previous ordering by rand.