I'm trying to select a particular row in a database using SELECT and OFFSET. The result I get is logical and I do get the desired row I want. But then I need to UPDATE that same specific row so I do something like that:
UPDATE table
SET value=1
WHERE value IN (SELECT * FROM(
SELECT value FROM table WHERE some criteria LIMIT 1 OFFSET 2) temp_tab);
Now what I expect from this code is to UPDATE the selected row ONLY. Instead it Updates ALL rows in the datatable and sets their value to 1.
When I use only:
SELECT * FROM(
SELECT value FROM table WHERE some criteria LIMIT 1 OFFSET 2) temp_tab
I get only 1 row as the output. (LIMIT 1 OFFSET 2 makes sure I do get the 1 row and it's the 2nd available) I am not exactly sure what I am doing wrong or how I am supposed to achieve this.
Note: I do have to use SELECT and not some other method using unique ID of the row or something similar.
Any help would be greatly appreciated.
First, when using LIMIT and OFFSET you need to use ORDER BY as well. Otherwise the row you get is indeterminate.
One method uses LIMIT within the UPDATE itself. However, UPDATE doesn't allow OFFSET. So:
UPDATE table
SET value = 1
WHERE some criteria
ORDER BY ??
LIMIT 1;
The best method would use a unique id. You can do this with the double subquery approach:
UPDATE table
SET value = 1
WHERE id IN (SELECT id
FROM (SELECT id
FROM table
WHERE some criteria
ORDER BY ??
LIMIT 1 OFFSET 2
) t
);
If you don't have a single unique id, you can use multiple columns that uniquely define a single row.
Related
I'm currently trying to setup a query that only selects from a row number and upwards from it. I've tried to use the LIMIT method in this way:
SELECT name FROM names LIMIT 1500, *
Which I expected to select from row number 1500 till the table's rows ended, but got a MySQL error instead.
I then tried to use a conditional for the ID of the rows like so:
SELECT name FROM names WHERE id >= 1500
Which gave unpredictable behavior since there are rows that get deleted, so it's not taking the real row numbers.
I think offset will do what you want. Unfortunately, MySQL requires a LIMIT value, but you can just put in a ridiculous number:
SELECT name
FROM names
OFFSET 1499
LIMIT 999999999;
you could use a subquery
select name
from names
where id > (
select max(id)
from names
order by names
limit 1500
)
Hello i have query in which i have written update statement using select statement. But unfortunately getting errors subquery returns more than 1 row. I know where the error is coming. But i dont know solution for the same.Thank you.
Here is the query:
UPDATE adsetest.dashboard_widget_users
SET configuration=
(SELECT DISTINCT ad_news_texte.headline
FROM autodo.ad_news_texte
INNER JOIN autodo.ad_news_oe
ON ad_news_texte.news_id = ad_news_oe.id_ad_news
INNER JOIN autodo.ad_news
ON ad_news_oe.id_ad_news = ad_news.id
WHERE ad_news.datum_archiv BETWEEN
curdate() - INTERVAL DAYOFWEEK(curdate()) + 28 DAY AND curdate())
WHERE dsnr_yw_user = 1 AND dsnr_dashboard_widget = 1
When you use update with SET configuration=(SELECT ...) the subquery has to return no more than one value (one row). If it returns more than one value how do you assign two rows table for example to scalar configuration field. So you should figure out WHY your subquery returns more than one row and fix the subquery or decide which ONE value to select for update in case of more than one row. For example you can select maximum value
SELECT MAX(ad_news_texte.headline)...
or any one first value
(SELECT ad_news_texte.headline)... LIMIT 1)
and so on...
If you need to concatenate all rows and put it into one row configureation you can use GROUP_CONCAT() mysql function:
SET configuration=(SELECT GROUP_CONCAT(DISTINCT ad_news_texte.headline) FROM ....
You have to first think about what you want to do.
Do you want to fetch one value and save it somewhere else?
Then use SET value = (SELECT...). For this you need to make sure, the inner statement doesn't return more than one value.
Or
Do you need to be able to handle fetching multiple values?
What do you want to do with these? Save all of them? All in one (use concat) or store them individually (one update per result)? Or select one of them? Maybe the first (LIMIT 1) or highest (MAX) or lowest (MIN) value?
Which of the following notations is better?
SELECT id,name,data FROM table WHERE id = X
OR
SELECT id,name,data FROM table WHERE id = X LIMIT 1
I think it should not have "LIMIT".
Thanks!
If there is a unique constraint on id then they will be exactly the same.
If there isn't a unique constraint (which I would find highly surprising on a column called id) then which is better depends on what you want to do:
If you want to find all rows matching the condition, don't use LIMIT.
If you want to find any row matching the condition (and you don't care which), use LIMIT 1.
Always use LIMIT with select statement even if you are fetching 1 record because it will speed up your query. So use :
SELECT id,name,data FROM table WHERE id = X LIMIT 1
For example :
If there are 1000 records in your table than if you using
SELECT id,name,data FROM table WHERE id = X
than it will traverse through 1000 records even if finds that id
But if you using LIMIT like this
SELECT id,name,data FROM table WHERE id = X LIMIT 1
than it will stop executing when finds first record.
When we are retrieving data from database, we use something like this
SELECT * FROM Names
However, we will get all the data inside the specific table. Since I am going to update some data to the database and want to make a comparison bewteen the last row of data in the db and the most updated data, how can I select and retrieve the last two row of the database only?
If you were using SQL Server, you would do something like this:
SELECT TOP 2 * FROM Names ORDER BY Name DESC
SQL Server syntax:
SELECT TOP 2 column_name FROM table_name ORDER BY column_name DESC;
Example:
If you want to retrieve the last value of the customer_name column from the customers table, you need to write the following query:
SELECT LAST (CUSTOMER_NAME) AS LAST_CUSTOMER FROM CUSTOMERS;
You should include a column in the Names table to keep track of when a name was added to the table since you cannot guarantee that the rows are in the order that they were inserted. With that column you can use the order by clause..
In MySQL Syntax:
SELECT *
FROM Names
ORDER BY order_column DESC
LIMIT 2;
If you want to get the last rows as they are, you cannot order the table by the inserted names because that is just getting the 2 names that come last in an alphabetically sorted list of names. You could try something like this where you include an offset in the limit clause if you get the number of rows in the table:
SELECT *
FROM Names
LIMIT *num_rows*-2, 2;
You would have to know the number of rows to use this query or use an additional query to implement a row count that works with limit. This, however, still may not be accurate since the system may not order the rows as they were inserted. I still recommend the first option where you keep track of order/time a name was inserted.
How can I SELECT the last row in a MySQL table?
I'm INSERTing data and I need to retrieve a column value from the previous row.
There's an auto_increment in the table.
Yes, there's an auto_increment in there
If you want the last of all the rows in the table, then this is finally the time where MAX(id) is the right answer! Kind of:
SELECT fields FROM table ORDER BY id DESC LIMIT 1;
Keep in mind that tables in relational databases are just sets of rows. And sets in mathematics are unordered collections. There is no first or last row; no previous row or next row.
You'll have to sort your set of unordered rows by some field first, and then you are free the iterate through the resultset in the order you defined.
Since you have an auto incrementing field, I assume you want that to be the sorting field. In that case, you may want to do the following:
SELECT *
FROM your_table
ORDER BY your_auto_increment_field DESC
LIMIT 1;
See how we're first sorting the set of unordered rows by the your_auto_increment_field (or whatever you have it called) in descending order. Then we limit the resultset to just the first row with LIMIT 1.
You can combine two queries suggested by #spacepille into single query that looks like this:
SELECT * FROM `table_name` WHERE id=(SELECT MAX(id) FROM `table_name`);
It should work blazing fast, but on INNODB tables it's fraction of milisecond slower than ORDER+LIMIT.
on tables with many rows are two queries probably faster...
SELECT #last_id := MAX(id) FROM table;
SELECT * FROM table WHERE id = #last_id;
Almost every database table, there's an auto_increment column(generally id )
If you want the last of all the rows in the table,
SELECT columns FROM table ORDER BY id DESC LIMIT 1;
OR
You can combine two queries into single query that looks like this:
SELECT columns FROM table WHERE id=(SELECT MAX(id) FROM table);
Make it simply use: PDO::lastInsertId
http://php.net/manual/en/pdo.lastinsertid.php
Many answers here say the same (order by your auto increment), which is OK, provided you have an autoincremented column that is indexed.
On a side note, if you have such field and it is the primary key, there is no performance penalty for using order by versus select max(id). The primary key is how data is ordered in the database files (for InnoDB at least), and the RDBMS knows where that data ends, and it can optimize order by id + limit 1 to be the same as reach the max(id)
Now the road less traveled is when you don't have an autoincremented primary key. Maybe the primary key is a natural key, which is a composite of 3 fields...
Not all is lost, though. From a programming language you can first get the number of rows with
SELECT Count(*) - 1 AS rowcount FROM <yourTable>;
and then use the obtained number in the LIMIT clause
SELECT * FROM orderbook2
LIMIT <number_from_rowcount>, 1
Unfortunately, MySQL will not allow for a sub-query, or user variable in the LIMIT clause
If you want the most recently added one, add a timestamp and select ordered in reverse order by highest timestamp, limit 1. If you want to go by ID, sort by ID. If you want to use the one you JUST added, use mysql_insert_id.
You can use an OFFSET in a LIMIT command:
SELECT * FROM aTable LIMIT 1 OFFSET 99
in case your table has 100 rows this return the last row without relying on a primary_key
Without ID in one query:
SELECT * FROM table_name LIMIT 1 OFFSET (SELECT COUNT(*) - 1 FROM table_name)
SELECT * FROM adds where id=(select max(id) from adds);
This query used to fetch the last record in your table.