mysql select inside limit - mysql

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;

Related

how to set the value of LIMIT using select count(id) from another table |MySQL

I have a scenario where the result must be limited depends on counting ids in another table.
Suppose i have these two tables counter and dispanser,
i want to select the last records in the table counter and limit the selection by counting the number of records in dispanser table.
something like this
select * from counter limit (select count(dispID) from dispanser)
You can't do this without using prepared statements or a stored procedure. From the manual:
LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants
In a stored procedure you could do something like this. COUNT(dispID) is stored into cnt and that variable is then used as the parameter to LIMIT. This is the exception to the above-mentioned rule.
DELIMITER //
CREATE PROCEDURE select_counter()
BEGIN
DECLARE cnt INT;
SELECT COUNT(dispID) INTO cnt FROM dispanser;
SELECT * FROM counter LIMIT cnt;
END //
DELIMITER ;
DBFiddle
Based on conversations in the comments, it sounds like what you're trying to do is get the count from counter for each record in dispanser - if this is wrong, please comment, and I can adjust my response. The best way to accomplish what you're looking for is through joining a subquery with the GROUP BY syntax. Something like this might could work, depending on your schema:
SELECT
d.*,
c.total
FROM
dispanser as d
INNER JOIN (
SELECT
COUNT(*) as 'total',
dispID
FROM
counter
GROUP BY
dispID
) as c
ON c.dispID = d.id
You can try to use dynamic SQL.
Set a variable #num to get an amount from dispanser table.
prepared your SQL statement CONCAT('select * from counter limit ', #num ).
Final use EXECUTE to execute SQL dynamically.
SET #sql = CONCAT('select * from counter order by counterID desc limit ', (SELECT count(dispID) from dispanser));
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
sqlfiddle

Limit by RAND without random order

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

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

SQL / Limit (another query)

I have 2 tables. One of them holds the limit numbers.
And i am trying to run an sql like
SELECT * FROM table WHERE x='1' LIMIT (another query)
The Select TOP clause limit the number of rows. You can put an expression in it
http://msdn.microsoft.com/en-us/library/ms189463.aspx
In MySQL you can't do that using regular querys.
LIMIT clause does not allow variables. LIMIT clause only accepts constant numbers.
You have to use Stored Procedures instead regular querys.
Try use something like this inside an SP code:
DECLARE offset bigint
SELECT your_field INTO offset FROM your_table where your_conditions
SELECT * FROM other_table LIMIT offset;
Use a prepared statement:
PREPARE stmt FROM "SELECT * FROM table WHERE x='1' LIMIT ?";
SET #limit = (another query);
EXECUTE stmt USING #limit;
\You do what I have suggested to several people is generate SQL from a select statement and then execute that. Here is my solution:
SELECT "select * from other_table LIMIT ", your_field
FROM your_table where your_conditions
Then execute this new SQL. Of course this works best in UNIX/Linux and with a scripting language.

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.