MySQL: Delete records based on maximum value - mysql

I have a table containing two foreign keys. I need to delete all rows where key1 & key2 are the same, but val < $x.
key1 & key2 aren't distinct values; there can be multiple records with the same key1 and/or key1/key2 pair.
I've tried several approaches, but can't get anything to work. Every approach thus far results in a MySQL error (such as "can't reopen table") or an incorrect result.
Sample data from the table:
rownum key1 key2 val col col2 col3 col4
1 123 1 2 a b c d
2 123 1 2 e f g h
3 123 2 3 i j k l
4 123 2 3 m n o p
5 456 1 1 q r s t
I need to delete all rows where "val" is < the highest "val" for any given key1/key2 pair.
In other words, for each distinct key1/key2 combo, I need to find the max "val" ($x), and delete any row where val is < $x.
Thus, the desired output after the delete statement is:
rownum key1 key2 val col col2 col3 col4
3 123 2 3 i j k l
4 123 2 3 m n o p
5 456 1 1 q r s t
(col-col4 are irrelevant in determining what records to delete, I included them only to note that the table includes additional columns.)
key1, key2, and "val" are all int type.
How can I delete rows where key1 & key2 are the same, but val < $x?

Use a multi-table delete syntax in which you join the table on itself using the key fields:
DELETE t1 FROM table1 t1, table1 t2
WHERE t1.key1=t2.key1 AND t1.key2=t2.key2 AND t1.val < t2.val
Sqlfiddle - I modified the sample data to have different vals for key pairs.

I'm not sure what your primary key is so I'm just going to call it primary_key
First we need to find the max of key2 for each key1
SELECT key1 as fk1, max(key2) as max_key2 from table group by key1
Then all rows where key2 < max_key2
SELECT t.primary_key as id, s.fk1, s.max_key2, t.key1 from table as t, (SELECT key1 as fk1, max(key2) as max_key2 from table group by key1) as s WHERE t.key2 < s.max_key2 AND s.fk1 = t.key1
Then delete those rows
DELETE from table where primary_key in (SELECT id from (SELECT t.primary_key as id, s.fk1, s.max_key2, t.key1 from table as t, (SELECT key1 as fk1, max(key2) as max_key2 from table group by key1) as s WHERE t.key2 < s.max_key2 AND s.fk1 = t.key1))
I have not tested this but it's roughly how i would go about the problem.
It should go without saying but validate before you delete and have backups

Related

Get count of all types of values in a column obtained in the same SELECT SQL query

MySQL Version: 5.7.36
I'm attempting to minimize the amount of queries I have to execute.
Right now, I'm executing a query similar to this:
SELECT
TABLE 1.column1 as "A",
TABLE 1.column2 as "B"
FROM
TABLE 1
WHERE
CONDITION
I can obtain the results I need from this query, however I would also like to obtain the count of what type of values show up in the same query.
For example, if the following query retrieves this table
A B
- -
1 a
1 b
1 c
2 d
3 e
4 f
4 g
I would also like to, for each row, obtain the count of all rows retrieved with its column "A" that matches its value.
Would it be more efficient to execute another query to get that result or can I modify my obtaining query to get this statistic?
Desired result:
A B C
- - -
1 a 3 # 3 rows with "1" in Column "A"
1 b 3
1 c 3
2 d 1
3 e 1
4 f 2
4 g 2
UPDATE:
The closest query I could find goes like this:
SELECT
TABLE 1.column1 as "A",
COUNT(TABLE 1.column1)
FROM
TABLE 1
WHERE
TABLE 1.column1 = "foo"
GROUP BY
TABLE 1.column1
Results in this:
A B C
- - -
1 a 3
2 d 1
3 e 1
4 f 2
However, it removes any other rows with the same value in column "A". Even if it has different values in column "B". I would like to have all rows present in my SQL query with its corresponding row count.
The next closest query I found goes like this:
SELECT
TABLE 1.column1 as "A",
COUNT(TABLE 1.column1)
FROM
TABLE 1
WHERE
TABLE 1.column1 = "foo"
GROUP BY
TABLE 1.column2
Results in this:
A B C
- - -
1 a 1
1 b 1
1 c 1
2 d 1
3 e 1
4 f 1
4 g 1
Which also isn't achieving the desired result.
You have to join with the subquery that gets the counts.
SELECT t1.column1 AS A, t1.column2 AS B, t2.count
FROM Table1 AS t1
JOIN (
SELECT column1 AS A, COUNT(*) AS count
FROM Table1
GROUP BY column1
) AS t2 ON t1.A = t2.A
SELECT
c,
COUNT(*) OVER (PARTITION BY c)
FROM t
ORDER BY c

MySQL Query to fetch count of a same successive two rows based on a column value

I need a sql query which will fetch me the count of unique possible combination of a value a to b of col3 based on the col2 value.
Here in the below table the value a to b is there twice(2 to 3 for col1-1 and 2 to 3 for col1-2).Similarly I need the count of such possible a to b fields as they appear successively in the table(which we can identify from col2-2,3)
I have the following table:
col1 col2 col3
1 2 a
1 3 b
1 4 c
2 2 a
2 3 b
2 4 c
Output:
f1 f2 count
a b 2
b c 2
Here col1+col2 is the primary key and the query should be generic for n no of possible successive combination.
As I was looking into possibilities of finding the solution to my problem, I got one by myself...
Below is the query to get the desired output which I wanted, was pretty straight forward.
select a.col3 f1,
b.col3 f2,
count(*) count
from testTable b,testTable a
where
a.col2 = b.col2 -1
and a.col1 = b.col1
group by ev1,ev2;

Access SQL Sub Query or Associative Array Statement

Field1 Field2 Field3
A 1 D 'should be dropped
A 1 K 'should be dropped
B 1 K
B 2 K
A 1 P 'should be dropped
A 2 P
A 1 M 'should be dropped
If Field3 = D then ANY ("A" "1") combination should be excluded regardless of Field 3 value. So in this example the first two records should not be returned.
So you have an existing query (we'll call it [TheThirdQuery]) that returns
Field1 Field2 Field3 comment
------ ------ ------ -----------------
A 1 D should be dropped
A 1 K should be dropped
B 1 K
B 2 K
A 1 P should be dropped
A 2 P
A 1 M should be dropped
If you want a query that will omit the rows as indicated in the [comment] column (without using the [comment] column itself), that query would be
SELECT * FROM TheThirdQuery t1
WHERE NOT EXISTS (
SELECT * FROM TheThirdQuery t2
WHERE t2.Field1=t1.Field1
AND t2.Field2=t1.Field2
AND t2.Field3='D'
)

Mysql delete duplicate rows + sort condition

I'm trying to delete some rows from my Mysql table, when one key is duplicate (here "url") and keep a particular one (here the smallest "key1" and "key2")
Example :
Table t1
Id Url Key1 Key2
1 A.com 10 10
2 B.com 20 25
3 B.com 21 25
4 C.com 35 35
5 C.com 35 37
Desired output is :
Table t1
Id Url Key1 Key2
1 A.com 10 10
3 B.com 21 25
5 C.com 35 37
So the query (if it exists) should look like :
Select rows where Url are duplicate
Then sort by Key1 and remove the row where Key1 is strictly inferior
if Key1 are equal, remove the row where Key2 is inferior
Thanks
You want to keep the rows where key1, key2 are maximal. An easy way to express this is:
delete t1 from table t1
where exists (select 1
from t1 t11
where t11.url = t1.url and
(t11.key1 > t1.key1 or
t11.key1 = t1.key1 and t11.key2 > t1.key2
)
);
Alas, MySQL doesn't allow this construct, because you using the table being deleted. So, you can do something like this:
delete t1
from t1 left join
(select t.*,
(select max(key2)
from t1
where t1.url = t.url and t1.key = t.maxkey1
) as maxkey2
from (select url, max(key1) as maxkey1
from t1
group by url
) t
) t
on t1.url = t.url and t1.key1 = t.maxkey1 and t2.key2 = t.maxkey2
where t.url is null;
I think this might be helpful
DELETE t1
FROM t1 as tb1
join t1 as tb2
WHERE tb1.url= tb2.url
and tb1.id < tb2.id
This way you keep the record with the max value on id column
but if you just want to fetch records
SELECT distinct tb1.*
FROM t1 as tb1
join t1 as tb2
WHERE tb1.url= tb2.url
and tb1.id < tb2.id

How to select values that already exists in column

I need to select all rows by value that posted more than one time.
Table:
key | value
------------
key1 | value
key2 | value
key2 | value
key3 | value
key3 | value
key4 | value
I need result like:
key2 | value
key3 | value
The below should get you what you need.
select key
from table
group by key
having count(*) > 1;
To find "duplicate" values of key, along with one of the values of value:
SELECT t.key
, MAX(t.value)
FROM mytable t
GROUP BY t.key
HAVING COUNT(1) > 1
To get (key,value) tuples that have "duplicates" in the table:
SELECT t.key
, t.value
FROM mytable t
GROUP
BY t.key
, t.value
HAVING COUNT(1) > 1