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
Related
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
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;
I want to limit selected all except 1st row.
Id is int, but not UNIQUE,
checkIn is date
SELECT * FROM table
Order by property_id, checkIn DESC
LIMIT 2, (SELECT Count(property_id)-1 FROM table)
Both Queries are working. but then I put them together i get
#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 '(SELECT Count(property_id) FROM table)' at line 1
Maybe here is universal key for all rows at LIMIT 1, ALL ?
If you need all rows except the first one, try this:
SELECT * FROM TBL LIMIT 1, 18446744073709551615;
18446744073709551615 is the recommend as a value as in the mysql docs and the maximum of a unsigned bigint.
There was a similar question.
For completeness, here's how you can do it with a prepared statement:
SET #skip=1;
SET #numrows=(SELECT Count(property_id)-1 FROM table);
PREPARE STMT FROM 'SELECT * FROM table Order by property_id, checkIn DESC LIMIT ?, ?';
EXECUTE STMT USING #skip, #numrows;
Although, if it's a InnoDB table, I wouldn't recommend to do a SELECT COUNT(*) on it repeatedly. Unlike MyISAM it doesn't store a row count in the table. Therefore counting on InnoDB can be slow when it has lots of rows.
P.S.: Note, that you have to use limit 1, how_many instead of limit 2, how_many when you want to skip one row, since it starts counting from 0, not from 1.
Johan already mentioned here
You can not use a subquery as a LIMIT argument. Limit argument
should be an INTEGER. You subquery returns, wel... basically, a
table.
From the MySQL manual
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, with these exceptions:
Within prepared statements, LIMIT parameters can be specified using ? placeholder markers.
Within stored programs, LIMIT parameters can be specified using integer-valued routine parameters or local variables as of MySQL 5.5.6.
Edit
Try like this
but i'm not tested
DECLARE offset bigint;
SELECT Count(property_id)-1 INTO offset FROM table;
SELECT * FROM table Order by property_id, checkIn DESC LIMIT 2,offset;
I agree with #omeinusch's answer, but also offer the following alternative:
SELECT * FROM table t JOIN (
SELECT property_id, checkIn
FROM table
ORDER BY property_id, checkIn DESC
LIMIT 2,1
) s ON (t.property_id > s.property_id)
OR (t.property_id = s.property_id AND t.checkIn <= s.checkIn)
If you have a unique id column, then you could do this:
select * FROM table
where id <> (SELECT id FROM table Order by property_id, checkIn DESC LIMIT 1)
Otherwise, assuming property_id and checkIn are unique,
select * FROM table
where concat(property_id,'|',checkIn) <>
(SELECT concat(property_id,'|',checkIn) FROM table Order by property_id, checkIn DESC LIMIT 1)
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.
I am new to MYSQL, and unable to resolve or even with so many answers on this forum, unable to identiy the error in this statement. I am using MYSQL database.
I have 2 tables: Ratemaster and rates, in which a customer can have 1 product with different rates.
Because of this, there is a duplication of customer and product fields, only the rate field changes.
Now Table Ratemaster has all the fields : id, Customer code, Product, Rate, user
whereas Table Rates has only: id, cust code, Rate, user.
- user field is for checking session_user.
Now Table Ratemaster has 3 records with all field values being same except Rate field empty.
Table Rates has different rates.
I want to have all rates to be updated in Ratemaster from Rates table. I am unable to do this with UPDATE and LIMIT mysql command, it is giving error as:
Incorrect usage of UPDATE and LIMIT
UPDATE Ratemaster, Rates
SET Ratemaster.Rate=Rates.Rate
WHERE Ratemaster.user=Rates.user
LIMIT 1
Usually you can use LIMIT and ORDER in your UPDATE statements, but in your case not, as written in the MySQL Documentation 12.2.10. UPDATE Syntax:
For the multiple-table syntax, UPDATE updates rows in each table named
in table_references that satisfy the conditions. In this case, ORDER
BY and LIMIT cannot be used.
Try the following:
UPDATE Ratemaster
SET Ratemaster.Rate =
(
SELECT Rates.Rate
FROM Rates
WHERE Ratemaster.user = Rates.user
ORDER BY Rates.id
LIMIT 1
)
Salam
You can use this method and work properly !
UPDATE Ratemaster, Rates
SET Ratemaster.Rate=Rates.Rate
WHERE Ratemaster.user=Rates.user
ORDER BY Rates.id
LIMIT 1
Work It 100%
UPDATE table SET Sing='p' ORDER BY sr_no LIMIT 10;
Read article about
How to use ORDER BY and LIMIT on multi-table updates in MySQL
For the multiple-table syntax, UPDATE updates rows in each table named
in table_references that satisfy the conditions. In this case, ORDER
BY and LIMIT cannot be used.
The problem is that LIMIT is only to be used with SELECT statements, as it limits the number of rows returned by the query.
From: http://dev.mysql.com/doc/refman/5.5/en/select.html
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, with these exceptions:
Within prepared statements, LIMIT parameters can be specified using ? placeholder markers.
Within stored programs, LIMIT parameters can be specified using integer-valued routine parameters or local variables as of MySQL 5.5.6.
With two arguments, the first argument specifies the offset of the
first row to return, and the second specifies the maximum number of
rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
To retrieve all rows from a certain offset up to the end of the result
set, you can use some large number for the second parameter. This
statement retrieves all rows from the 96th row to the last:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
With one argument, the value specifies the number of rows to return
from the beginning of the result set:
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
In other words, LIMIT row_count is equivalent to LIMIT 0, row_count.
For prepared statements, you can use placeholders. The following
statements will return one row from the tbl table:
SET #a=1; PREPARE STMT FROM 'SELECT * FROM tbl LIMIT ?'; EXECUTE STMT
USING #a;
The following statements will return the second to sixth row from the
tbl table:
SET #skip=1; SET #numrows=5; PREPARE STMT FROM 'SELECT * FROM tbl
LIMIT ?, ?'; EXECUTE STMT USING #skip, #numrows;
For compatibility with PostgreSQL, MySQL also supports the LIMIT
row_count OFFSET offset syntax.
If LIMIT occurs within a subquery and also is applied in the outer
query, the outermost LIMIT takes precedence. For example, the
following statement produces two rows, not one:
(SELECT ... LIMIT 1) LIMIT 2;