How to delete all rows except the 50 newest - mysql

how i can delete all rows in table recentposts
DELETE FROM recentposts WHERE recentposts.`userId` = 12 AND recentposts.`Id`
NOT IN (SELECT * FROM recentposts WHERE `userId` = 12 ORDER BY viewdate LIMIT 50)
i try many similar to this but they not worked. can someone tell me how i can do this in Mysql.

What about this?
DELETE FROM recentposts
WHERE
recentposts.`userId` = 12
AND
recentposts.`Id` NOT IN (SELECT Id
FROM recentposts
WHERE `userId` = 12
ORDER BY viewdate DESC LIMIT 50)

DELETE FROM `recentpost`
WHERE WHERE userId = 12 AND id NOT IN (
SELECT id
FROM (
SELECT id
FROM `table`
ORDER BY id DESC
LIMIT 50
) foo
);
PS: only working (MySQL 5.0.67 and upper) AS in earlier versions These are limitations of MySQL.
you can't DELETE and SELECT from a given table in the same query.
MySQL does not support LIMIT in a subquery.
so for previous version u can come up with is to do this in two stages:
first step
SELECT id FROM mytable ORDER BY id DESC LIMIT n;
Collect the id's and make them into a comma-separated string:
DELETE FROM mytable WHERE id NOT IN ( ...comma-separated string... );

Related

How Can I Sort SQL Results From Smallest Index To Largest Index?

I have a database that is sorted by ID. I want to echo out the 3 rows with the biggest id number but have them echoed out as
id = 5
id = 6
id = 7
as opposed to how
SELECT * FROM `userinfo`ORDER BY `id` ASC LIMIT 3;
will echo out
id = 7
id = 6
id = 5
in PHP
Use a derived table for limiting the result and sort again in the outer query.
SELECT *
FROM (SELECT *
FROM `userinfo`
ORDER BY `id` DESC
LIMIT 3) x
ORDER BY `id` ASC;

MySQL - Sort table efficiently when querying by another attribute

On this JS fiddle:
http://sqlfiddle.com/#!9/4c7bc0/7
CREATE TABLE big_table(id INTEGER AUTO_INCREMENT PRIMARY KEY,
user_id INTEGER NOT NULL);
The second query
SELECT * FROM big_table WHERE user_id IN ( 1, 100, 1000 )
ORDER BY id DESC LIMIT 10;
Is planned as: Using where; Using index; Using filesort
When big_table contains tens of millions of rows, the filesort kills the performance.
How do I ORDER BY faster?
For this query:
SELECT *
FROM big_table
WHERE user_id IN ( 1, 100, 1000 )
ORDER BY id DESC
LIMIT 10;
You cannot easily get rid of the work for the ORDER BY (there is one possible way, see below). Most importantly, you need an index on big_table(user_id):
CREATE INDEX idx_bigtable_userid ON big_table(user_id);
If there are only a few dozen or hundreds of rows that match, then this should be fine.
Another possibility is to rewrite the query, and use an index on:
CREATE INDEX idx_bigtable_userid ON big_table(user_id, id);
I should start by saying that I'm not 100% sure that this approach will work because of the DESC on id. But, the following query should use the index:
SELECT *
FROM big_table
WHERE user_id = 1
ORDER BY id DESC;
So you can do:
SELECT *
FROM ((SELECT t.*
FROM big_table t
WHERE t.user_id = 1
ORDER BY id DESC
LIMIT 10
) UNION ALL
(SELECT t.*
FROM big_table t
WHERE t.user_id = 100
ORDER BY id DESC
LIMIT 10
) UNION ALL
(SELECT t.*
FROM big_table t
WHERE t.user_id = 1000
ORDER BY id DESC
LIMIT 10
)
) t
ORDER BY id DESC
LIMIT 10;

update row if count(*) > n

my DB has this structure:
ID | text | time | valid
This is my current code. I'm trying to find a way to do this as one query.
rows = select * from table where ID=x order by time desc;
n=0;
foreach rows{
if(n > 3){
update table set valid = -1 where rows[n];
}
n++
}
I'm checking how many rows exist for a given ID. Then I need to set valid=-1 for all rows where n >3;
Is there a way to do this with one query?
You can use a subquery in the WHERE clause, like this:
UPDATE table
SET valid=-1
WHERE (
SELECT COUNT(*)
FROM table tt
WHERE tt.time > table.time
AND tt.ID = table.ID
) > 3
The subquery counts the rows with the same ID and a later time. This count will be three or less for the three latest rows; the remaining ones would have a greater count, so their valid field would be updated.
Assuming that (id,time) has a UNIQUE constraint, i.e. no two rows have the same id and same time:
UPDATE
tableX AS tu
JOIN
( SELECT time
FROM tableX
WHERE id = #X -- the given ID
ORDER BY time DESC
LIMIT 1 OFFSET 2
) AS t3
ON tu.id = #X -- given ID again
AND tu.time < t3.time
SET
tu.valid = -1 ;
update table
set valid = -1
where id in (select id
from table
where id = GIVEN_ID
group by id
having count(1) >3)
Update: I really like dasblinkenlight's solution because is very neat, but I wanted to try also to do it in my way, a quite verbose one:
update Table1
set valid = -1
where (id, time) in (select id,
time
from (select id,time
from table1
where id in (select id
from table1
group by id
having count(1) >3)
-- and id = GIVEN_ID
order by time
limit 3, 10000000)
t);
Also in SQLFiddle
to do it for all ids, or only for one if you set a where in the a subquery
UPDATE TABLE
LEFT JOIN (
SELECT *
FROM (
SELECT #rn:=if(#prv=id, #rn+1, 1) AS rId,
#prv:=id AS id,
TABLE.*
FROM TABLE
JOIN ( SELECT #prv:=0, #rn:=0 ) tmp
ORDER BY id, TIMESTAMP
) a
WHERE rid > 3
) ordered ON ordered.id = TABLE.id
AND ordered.TIMESTAMP = TABLE.TIMESTAMP
AND ordered.text = TIMESTAMP.text
SET VALID = -1
WHERE rid IS NOT NULL

Mysql delete order by

I have a table and I only display the latest 30 rows by order by ID.
I'm trying to delete any rows after the 30 newest rows by using this query below.
DELETE FROM table WHERE type = 'test' ORDER BY id DESC LIMIT 30, 60
I keep getting this error below
#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 ' 60' at line 1
What am I doing wrong?
Try this one,
DELETE FROM table
WHERE ID IN
(
SELECT ID
FROM
(
SELECT ID
FROM table
WHERE Type = 'TEST'
ORDER BY ID
LIMIT 30,60
) a
)
Second edit: While MySQL supports LIMIT in delete statements, it does not allow an OFFSET. This means that you cannot skip the first 30 rows.
Make a subselect on id (or any other primary key):
DELETE FROM table WHERE id IN (SELECT id FROM table WHERE type = 'test' ORDER BY id DESC LIMIT 30, 60)
This is not possible this way.
You could try it with a nested select statement, somewhat like this:
DELETE FROM table
WHERE type = 'test'
AND ID IN (SELECT id from table where type = 'test' order by id desc limit 30 )
Try like this
DELETE FROM table WHERE id in(SELECT id FROM table WHERE type = "test" order by id desc limit 30, 60)
I was unable to use the limit clause in the sub-query, so the solution I use, somewhat messy, is:-
select group_concat(id) into #idList from
(
select id from table order by id desc limit 0,30
) as saveIds;
delete from table where not find_in_set(id,#idList)
Alternatively,
select group_concat(id) into #idList from
(
select id from table order by id desc limit 30
) as saveIds;
delete from table where find_in_set(id,#idList)

How to find the previous and next record using a single query in MySQL?

I have a database, and I want to find out the previous and next record ordered by ID, using a single query. I tried to do a union but that does not work. :(
SELECT * FROM table WHERE `id` > 1556 LIMIT 1
UNION
SELECT * FROM table WHERE `id` <1556 ORDER BY `product_id` LIMIT 1
Any ideas?
Thanks a lot.
You need to change up your ORDER BY:
SELECT * FROM table WHERE `id` > 1556 ORDER BY `id` ASC LIMIT 1
UNION
SELECT * FROM table WHERE `id` < 1556 ORDER BY `id` DESC LIMIT 1
This ensures that the id field is in the correct order before taking the top result.
You can also use MIN and MAX:
SELECT
*
FROM
table
WHERE
id = (SELECT MIN(id) FROM table where id > 1556)
OR id = (SELECT MAX(id) FROM table where id < 1556)
It should be noted that SELECT * is not recommended to have in production code, though, so name your columns in your SELECT statement.