select and delete rows within groups using mysql

自古美人都是妖i 提交于 2020-01-04 06:27:10

问题


I've seen examples for duplicate row manipulation, but I can't figure out how to map them to solve my problem.

+----+------------+------+---------+
| id | date       | file | status  |
+----+------------+------+---------+
|  1 | 2011-12-01 |    1 | Pending |
|  2 | 2011-12-02 |    1 | Pending |
|  3 | 2011-12-03 |    1 | Done    |
|  4 | 2011-12-04 |    1 | Pending |
|  5 | 2011-12-05 |    1 | Done    |
|  6 | 2011-12-06 |    1 | Pending |
|  7 | 2011-12-07 |    1 | Pending |
|  8 | 2011-12-08 |    1 | Pending |
|  9 | 2011-12-09 |    2 | Pending |
| 10 | 2011-12-10 |    2 | Pending |
| 11 | 2011-12-11 |    3 | Pending |
| 12 | 2011-12-12 |    4 | Done    |
| 13 | 2011-12-13 |    5 | Pending |
| 14 | 2011-12-14 |    5 | Done    |
| 15 | 2011-12-15 |    5 | Pending |
+----+------------+------+---------+

For each file in the table:

  1. I need to first select/delete any row where status='Pending', and its date is older than the youngest date for any row where status='Done'. For the example, this would select/delete rows with id 1, 2, 4, and 13.

  2. I need to next select/delete any row where status='Pending' and it's not the oldest date where status='Pending'. For the example, this would select/delete rows with id 7, 8, and 10.

The resulting table is:

+----+------------+------+---------+
| id | date       | file | status  |
+----+------------+------+---------+
|  3 | 2011-12-03 |    1 | Done    |
|  5 | 2011-12-05 |    1 | Done    |
|  6 | 2011-12-06 |    1 | Pending |
|  9 | 2011-12-09 |    2 | Pending |
| 11 | 2011-12-11 |    3 | Pending |
| 12 | 2011-12-12 |    4 | Done    |
| 14 | 2011-12-14 |    5 | Done    |
| 15 | 2011-12-15 |    5 | Pending |
+----+------------+------+---------+

This will create and populate the test table in MySQL:

CREATE TABLE test ( id int(11) NOT NULL AUTO_INCREMENT, date date DEFAULT NULL, file int(11) DEFAULT NULL, status varchar(45) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=latin1;

INSERT INTO test VALUES (1,'2011-12-01',1,'Pending '),(2,'2011-12-02',1,'Pending '),(3,'2011-12-03',1,'Done'),(4,'2011-12-04',1,'Pending '),(5,'2011-12-05',1,'Done'),(6,'2011-12-06',1,'Pending '),(7,'2011-12-07',1,'Pending '),(8,'2011-12-08',1,'Pending '),(9,'2011-12-09',2,'Pending '),(10,'2011-12-10',2,'Pending '),(11,'2011-12-11',3,'Pending '),(12,'2011-12-12',4,'Done'),(13,'2011-12-13',5,'Pending '),(14,'2011-12-14',5,'Done'),(15,'2011-12-15',5,'Pending ');


Thanks to ziesemer for the correct SELECT queries--I learned a lot from them. Unfortunately, it appears that MySQL doesn't allow DELETE with a subquery, so I converted ziesemer's answer to use JOINS instead. But I'm a SQL noob, so please correct if these could be improved:

SELECT DISTINCT t1.* FROM test t1 INNER JOIN test t2
 WHERE t1.file = t2.file
   AND t1.status = 'Pending'
   AND t2.status = 'Done'
   AND t1.date < t2.date;

SELECT DISTINCT t1.* FROM test t1 INNER JOIN test t2
 WHERE t1.file = t2.file
   AND t1.status = 'Pending'
   AND t2.status = 'Pending'
   AND t1.date > t2.date;

To delete, replace the SELECT line with:

DELETE t1 FROM test t1 INNER JOIN test t2

回答1:


I have these tested, working independently - though the 2nd must be executed after the 1st to get the results you provided in your example. I am having some difficulty getting them to work as one Select, as the 2nd query is dependent upon the state of the table after the 1st is complete...

Select *
    From my_table t1
    Where (status = 'Pending'
        And date < (
            Select Max(date)
                From my_table t2
                Where t2.file = t1.file
                    And t2.status = 'Done'));

Select *
    From my_table t1
    Where (status = 'Pending'
        And date > (
            Select Min(date)
                From my_table t2
                Where t2.file = t1.file
                    And t2.status = 'Pending'));

(I'll give a +1 to anyone else who's answer can do this in one query, while producing the same, accurate results - I'm stumped, for now.)




回答2:


Your first problem will be solved by the below query, just you need to to do a subselect:

delete from tables1 where (select * from table1 where status=pending AND file=1 AND date>2011-12-05)

for the other one it needs a little thinking. (let me think about it)



来源:https://stackoverflow.com/questions/8622513/select-and-delete-rows-within-groups-using-mysql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!