Delete records with multiple conditions - mysql

I need to exclude duplicate records in the bidding_price column with the following conditions:
Table: bid_account
Columns to check:
id = PRIMARY KEY auction_id = ID of each product
bidding_price = inserted value (this must be checked for duplicity for each product)
bid_flag = must always equal the value of: 'd' bidding_type = must always equal the value of:: 's'
It will always exist equal records in the bidding_price column, which it can not have is equal records with the same product ID (auction_id).
Example of how it should not have:
auction_id | bidding_price
------10------------0.02
------10------------0.02
------11------------0.02
------11------------0.02
The correct would be:
auction_id | bidding_price
------10------------0.02
------11------------0.02
I tried with the following command:
DELETE ba
FROM bid_account ba JOIN
(SELECT ba2.auction_id, ba2.bidding_price, MAX(ba2.id) as max_id
FROM bid_account ba2
WHERE ba2.bid_flag = 'd' AND ba2.bidding_type = 's'
GROUP BY ba2.auction_id, ba2.bidding_price
) ba2
ON ba2.auction_id = ba.auction_id AND
ba2.bidding_price = ba.bidding_price AND
ba2.max_id < ba.id
WHERE ba.bid_flag = 'd' AND ba.bidding_type = 's' AND ba.auction_id = ba2.auction_id
The problem is that it deleted multiple records that it should not delete, did not do the validations correctly. How can I do it?

ID is your PRIMARY KEY in the table, so you can get MAX(id) to be your
Reservation ID,then use NOT IN to delete by ID without MAX(id)
You can try this.
DELETE ba FROM bid_account ba
WHERE ba.id NOT IN
(
SELECT max_id FROM
(
SELECT auction_id, bidding_price, MAX(id) max_id
FROM bid_account
WHERE bid_flag = 'd' AND bidding_type = 's'
GROUP BY auction_id, bidding_price
) t
)
sqlfiddle:http://sqlfiddle.com/#!9/0f2e5/1
EDIT
If you want to get lowest-value ID you could use MIN(id) in the subquery in the where clause
DELETE ba FROM bid_account ba
WHERE ba.id NOT IN
(
SELECT min_id FROM
(
SELECT auction_id, bidding_price, MIN(id) min_id
FROM bid_account
WHERE bid_flag = 'd' AND bidding_type = 's'
GROUP BY auction_id, bidding_price
) t
)
sqlfiddle:http://sqlfiddle.com/#!9/ffe92/1

You can delete it by using your PRIMARY KEY: ID.
It is used to uniquely identify the record for delete action.
See demo here: http://sqlfiddle.com/#!9/603d56/1
It makes use of selecting the ID within a subquery(selecting it twice will AVOID the error: target table cannot be specified for update). The subquery is similar to your query and it selects the id that will be retained. Using NOT IN means delete the rest of the rows not equal to these ids in the subquery.
delete e.*
from bid_account e
where e.id not in (
select id from (
select a.id
from bid_account a
join bid_account b
on a.auction_id=b.auction_id
and a.bidding_price=b.bidding_price
and a.bid_flag=b.bid_flag
and a.bidding_type=b.bidding_type
where a.bid_flag='d' and a.bidding_type='s'
and a.id < b.id) tt);

The below statement should give you all the records that you need.
SELECT ba2.auction_id, ba2.bidding_price, MAX(ba2.id) as max_id
FROM bid_account ba2
WHERE ba2.bid_flag = 'd' AND ba2.bidding_type = 's'
GROUP BY ba2.auction_id, ba2.bidding_price;
A not-in clause should give you all the records that you don't need.
So, delete from bid_account where id not in (#sub query to fetch required ids#) and ba.bid_flag = 'd' AND ba.bidding_type = 's'; should delete the duplicate records.

Related

Delete duplicates with condition

I have the table contacts which contains duplicate records:
id name is_contacted created_at
I need to delete duplicates, but keep the first record(among the duplicates for each name) where is_contacted=1.
If among the record duplicates there are no records where is_contacted=1, just keep the first one.
This is what I have so far:
DELETE c1 FROM contacts c1
INNER JOIN contacts c2
WHERE
c1.id > c2.id AND
c1.name = c2.name;
Assuming that is_contacted's data type is BOOLEAN and id is the primary key of the table and this is the column that defines the order and which row should be considered first, use ROW_NUMBER window function to rank the rows of each name:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY name ORDER BY is_contacted DESC, id) rn
FROM contacts
)
DELETE t
FROM contacts t INNER JOIN cte c
ON c.id = t.id
WHERE c.rn > 1;
ORDER BY is_contacted DESC, id returns the rows with is_contacted = 1 at the top (if they exist).
For versions of MySql prior to 8.0, without support of CTEs and winow functions, use a join of the table to a query that uses aggregation to get the id of the row that you want to keep:
DELETE t
FROM contacts t
INNER JOIN (
SELECT name,
COALESCE(MIN(CASE WHEN is_contacted THEN id END), MIN(id)) id
FROM contacts
GROUP BY name
) c ON c.name = t.name AND c.id <> t.id;
Below query will filter only records what you want.
You didn't mention what is primary key in your table, so I don't know how to join this back 1:1 with your whole table.
But if you are not able to determine primary key, they you can create new table using this query, drop original one and rename it to original one.
SELECT * FROM
(
SELECT *,
ROW_NUMBER(PARTITION BY name ORDER BY CASE WHEN is_contacted = 1 THEN -999999 else is_contacted END ) AS RN_
from contacts
) c
WHERE c.RN_ = 1

MySQL Query to rename duplicate column

Thanks to this question Rename Mysql Duplicate Value I was able to come up with this queryn to elminate the duplicate rows.
UPDATE table1
inner join (SELECT OBJECTID,CONCAT(IDENT,'_1') as IDENT FROM table1
GROUP BY IDENT HAVING COUNT(*) > 1) t
on t.OBJECTID = table1.OBJECTID
SET table1.IDENT = t.IDENT;
This works well but I want to only rename the rows where the column IDENT is duplicated and the NAME column is different. Any ideas how to do this?
Change the grouping to be both NAME and IDENT.
UPDATE table1
JOIN (
SELECT MAX(objectid) AS max_id, name, CONCAT(ident, '_1') AS new_ident
FROM table1
GROUP BY name, ident
HAVING COUNT(*) > 1
) AS t ON t.max_id = table1.objectid
SET table1.ident = t.new_ident

Reduce not null duplicate rows in MySQL from many to one

I need an update statement to resolve some issues with duplicates in a table on MySQL. The table structure is shown below. I need a MySQL statement that will set the value of duplicate as NULL except the first one, i.e the one with the lowest id. Here the id is the primary key.
This is an example of what I have:
id name
1 foo
2 foo
3 bar
4 NULL
5 NULL
6 foo
7 bar
This is the desired result:
id name
1 foo
2 NULL
3 bar
4 NULL
5 NULL
6 NULL
7 NULL
The table has other columns with useful information. Hence, the row can't just simply be deleted.
I would write this as:
UPDATE t JOIN
(SELECT name, MIN(id) as min_id
FROM t
GROUP BY name
) tt
ON t.name = tt.name and t.id > tt.min_id
SET t.name = NULL;
I think the logic is easier to follow using JOIN. Basically, it says to find the minimum id for each name. Then set all other rows for the same name to NULL.
Your UPDATE query can include a JOIN.
e.g. join the minimum id for each name and only update where the id is not the minimum.
UPDATE
t
LEFT OUTER JOIN (
SELECT
MIN(id) AS id
FROM
t
GROUP BY
name
) t1 ON t.id = t1.id
SET
t.name = NULL
WHERE
t1.id IS NULL
DB Fiddle
UPDATE t JOIN
(SELECT name, MIN(id) as min_id
FROM t
WHERE name IS NOT NULL
GROUP BY name
HAVING COUNT(*) > 1
) tt
ON t.name = tt.name and t.id > tt.min_id
SET t.name = NULL;

Delete duplicate records in MYSQL with condition

I am using a command that runs every second on node.js It has the function of excluding any duplicate records for a given item, which is specified as in the example by: AND t1.auction_id = 1335.
DELETE FROM bid_account t1
WHERE t1.id < (Select max(t1.id) FROM bid_account t2 WHERE t1.bidding_price = t2.bidding_price) AND t1.auction_id = 1335;
I need it to delete a record that has an equal value in the bidding_price column, and keep only one. But it is important that he does this search not across the table, but rather for a certain item as I reported at the beginning, through the column auction_id.
I tried to run the above command, but it returns the following error:
#1064 - You have a syntax error in your SQL next to 't1
WHERE t1.id < (Select max(t1.id) FROM bid_account t2 WHERE t1.bidding_price ' na linha 1
What is wrong with this query?
I use the MYSQL database, and the table bid_account has the id column as index and primary.
If I use SELECT below, it returns the values in duplicity normally.
SELECT bidding_price, count(*) FROM bid_account WHERE `auction_id` = 1335 GROUP BY bidding_price Having Count(*) > 1
You have two quirks from MySQL. First, when you use an alias for a table, it needs to follow the DELETE. So, this is what you intend:
DELETE ba FROM bid_account ba
WHERE ba.id < (Select max(ba2.id) -- I assume you want the max from the innter reference
FROM bid_account ba2
WHERE ba2.bidding_price = ba.bidding_price
) AND
ba.auction_id = 1335;
However, this still will not work, because you are referencing bid_account in the table.
So, I think you want something more like this:
DELETE ba
FROM bid_account ba JOIN
(SELECT ba2.auction_id, ba2.bidding_price, MAX(ba2.id) as max_id -- I assume you want the max from the innter reference
FROM bid_account ba2
WHERE ba2.auction_id = 1335
GROUP BY ba2.auction_id, ba2.bidding_price
) ba2
ON ba2.auction_id = ba.ba2.auction_id AND
ba2.bidding_price = ba.bidding_price AND
ba2.max_id > ba.id
WHERE ba.auction_id = 1335;
This still doesn't strike me as useful. Matching rows based on bidding_price seems unusual. I would expect auction_id to be part of the match. I suspect you want to GROUP BY and JOIN on both bidding_price and auction_id.
You can delete row by using alias before from keyword in sql query
for example
delete t from test t where t.id = 3
So your query will work fine
DELETE t1 FROM bid_account t1
WHERE t1.id < (Select max(t1.id) FROM bid_account t2 WHERE t1.bidding_price = t2.bidding_price) AND t1.auction_id = 1335;

Delete duplicates in mysql when based on values from 3 columns matching

I have the query below that shows me duplicates in my table. I would like to know how can i turn this into a delete query to delete these duplicate rows but leaving just one. My table does have a auto increment id column.
SELECT * FROM tbl_user_tmp AS t1
INNER JOIN (
SELECT name, activity, class, COUNT(1) AS cnt FROM tbl_user_tmp
WHERE user = 'test' AND disregard = 0
GROUP BY name, activity, class
HAVING cnt > 1
) AS t2
ON t1.name = t2.name AND t1.activity = t2.activity AND t1.class = t2.class
WHERE user = 'test' AND disregard = 0
GROUP BY t1.name, t1.activity, t1.class
I have tried the query below and seems to work, but im afraid im missing something. does it look correct?
delete from tbl_user_tmp
where user='test' AND id not in
(
select minid from
(select min(id) as minid from tbl_user_tmp where user='test' group by name, activity, class) as newtable
)
You can use LIMIT.
Example:
DELETE FROM users
LIMIT 2;
Now you just need to set COUNT - 1 as your limit ;)