trimming MySQL table - mysql

I would like to trim an existing MySQL ISAM table, 10million records.
What would be a SQL statement to delete the last 5million records? This is just a log table, no damage done by removing records.

delete from table where id >= (select * from (select id from table order by id limit 4999999,1) as t )

You can use ORDER BY and LIMIT with DELETE to affect only a limited number of rows. The way that you would get the 'last' 5 million depends on what you have as far as determining record age, and use that in your ORDER BY.

SELECT *
FROM ??? (youre table name)ORDER BY?????? LIMIT 5000000
Here ??? = youre table name, and ?????? is the way you sort youre table. So if you have some sort of date or number of entry to sort by.
http://www.w3schools.com/sql/
I've used SELECT in my example above so you can try out first if it works correctly! If it does work, change SELECT into DELETE :)
If it doesn't work, than you've to try something else to sort by :)

Does this works
DELETE FROM tableA ORDER BY some_indexed_column DESC LIMIT 1000000

Related

Retrieve all records with LIMIT in mysql

I have the following MySQL query;
SELECT records FROM users
LIMIT 1
One record will be retrieved. Suppose I want to retrieve all records but still use the keyword LIMIT. Can I do something like this?
SELECT records FROM users
LIMIT ALL
Just use
SELECT records FROM users
Do not use LIMIT at all
Or if it is required to use LIMIT , use a very high number
SELECT records FROM users LIMIT 999999999999
You have to just make up a ridiculous number and limit it by that.
E.g. SELECT records FROM users LIMIT 18446744073709551615 if you really want to keep the limit clause. This is similar to using offset to infinite amount.
According to mysql doc you are supposed to use a very large number.
SELECT * FROM tbl LIMIT 95,18446744073709551615;
Terrible solution, if you ask me, but its from the mysql documentation
http://dev.mysql.com/doc/refman/5.0/en/select.html#id4651990
If you want to retrieve all data then just use
select * from tbl;

How do I select a record whose timestamp is the most recent

I have a mysql db which one of the columns is of type timestamp. And the records look like this
How do I select the most recent timestamp in a query and display it?
SELECT * FROM tbl ORDER BY created_ts DESC LIMIT 1
PS: you should use hashed passwords rather than plain-text ones
It's simple:
SELECT * FROM TABLE ORDER BY CREATED_TS LIMIT 1
I guess its better to index the sequence ID and get the max from there. Getting max of your timestamp will run into real performance issues when your table grows big.

Select last row in MySQL

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.

MySQL: how to keep top 1000 rows for each value of a column

I need some help with this query: I want to delete the following rows from my table.
The table has 4 columns: UserID, UserName, Tag, Score.
I want to keep only the top 1000 users with highest score, for each Tag.
So I need to order by score, and to keep the first 1000 users for each tag.
Thanks
Based on the other answer,
DELETE FROM table t1
WHERE UserID NOT IN (SELECT userID FROM table t2
WHERE t2.tag = t1.tag
ORDER BY Score DESC LIMIT 1000);
This assumes that UserID is a unique/primary key field. If it's not, you could do something like this:
DELETE FROM table t1
WHERE UserID||' '||Tag NOT IN (SELECT UserID||' '||Tag FROM table t2
WHERE t2.tag = t1.tag
ORDER BY Score DESC LIMIT 1000);
Putting the spaces in because I know I've had to do similar on Oracle, not sure how MySQL would handle it without.
You should be able to fix this with a subquery although I'm not completely sure if MySQL supports that within delete queries. I do know that it can give problems with update queries (I've had some segfaults in MySQL because of this)
Either way... this should work (atleast, it would in Postgres)
DELETE FROM table WHERE id NOT IN (SELECT id FROM table ORDER BY Score DESC LIMIT 1000)
Assuming that id is your primary key ofcourse.
Solution using a temporary table:
Do note that you'll have to repeat this process for every tag. I can't think of a way to do it in 1 query in MySQL 5.0
CREATE TEMPORARY TABLE top_users
SELECT * FROM table
WHERE Tag = ...
GROUP BY UserID
ORDER BY Score DESC
LIMIT 1000;
DELETE FROM table WHERE Tag = ...;
INSERT INTO table
SELECT * FROM top_users;
Maybe a temporary table, who is filled with a select clause
SELECT * FROM table ORDER BY Score DESC LIMIT 1000;
I dont have the syntax handy for creating the temporary table, but that will atleast get your the rows you want.
Be careful with delete commands... Better to create a new view/table.

What's the most efficient way to select the last n rows in a table without changing the table's structure?

What's the most efficient way to select the last n number of rows in a table using mySQL? The table contains millions of rows, and at any given time I don't know how large the table is (it is constantly growing). The table does have a column that is automatically incremented and used as a unique identifier for each row.
SELECT * FROM table_name ORDER BY auto_incremented_id DESC LIMIT n
Actually the right way to get last n rows in order is to use a subquery:
(SELECT id, title, description FROM my_table ORDER BY id DESC LIMIT 5)
ORDER BY tbl.id ASC
As this way is the only I know that will return them in right order. The accepted answer is actually a solution for "Select first 5 rows from a set ordered by descending ID", but that is most probably what you need.
(Similar to "marco"s answer,)
my fav is the max()-function of MySQL too, in a simple one-liner, but there are other ways of sure:
SELECT whatever FROM mytable WHERE id > (SELECT max(id)-10 FROM mytable);
... and you get "last id minus 10", normally the last 10 entries of that table.
It's a short way, to avoid the a error 1111 ("Invalid use of group function") not only if there is a auto_increment-row (here id).
The max()-function can be used many ways.
Maybe order it by the unique id descending:
SELECT * FROM table ORDER BY id DESC LIMIT n
The only problem with this is that you might want to select in a different order, and this problem has made me have to select the last rows by counting the number of rows and then selecting them using LIMIT, but obviously that's probably not a good solution in your case.
Use ORDER BY to sort by the identifier column in DESC order, and use LIMIT to specify how many results you want.
You would probably also want to add a descending index (or whatever they're called in mysql) as well to make the select fast if it's something you're going to do often.
This is a lot faster when you have big tables because you don't have to order an entire table.
You just use id as a unique row identifier.
This is also more eficient when you have big amounts of data in some colum(s) as images for example (blobs). The order by in this case can be very time and data consuming.
select *
from TableName
where id > ((select max(id) from TableName)-(NumberOfRowsYouWant+1))
order by id desc|asc
The only problem is if you delete rows in the interval you want. In this case you would't get the real "NumberOfRowsYouWant".
You can also easily use this to select n rows for each page just by multiplying (NumberOfRowsYouWant+1) by page number when you need to show the table backwards in multiple web pages.
Here you can change table name and column name according your requirement . if you want to show last 10 row then put n=10,or n=20 ,or n=30 ...etc according your requirement.
select * from
(select * from employee
Order by emp_id desc limit n)
a Order by emp_id asc;