使用mysql选择和删除组内的行

时间:2011-12-24 03:38:01

标签: mysql group-by duplicates

我已经看过重复行操作的示例,但我无法弄清楚如何映射它们来解决我的问题。

+----+------------+------+---------+
| 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 |
+----+------------+------+---------+

对于表格中的每个文件:

  1. 我需要首先选择/删除状态='待定'的任何行,并且其日期早于状态='完成'的任何行的最新日期。 。例如,这将选择/删除id为1,2,4和13的行。

  2. 我需要接下来选择/删除状态='待定'并且它不是状态='待定'的最早的日期。例如,这将选择/删除ID为7,8和10的行。

  3. 结果表是:

    +----+------------+------+---------+
    | 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 |
    +----+------------+------+---------+
    

    这将在MySQL中创建并填充测试表:

    CREATE TABLE test(   id int(11)NOT NULL AUTO_INCREMENT,   date日期DEFAULT NULL,   file int(11)DEFAULT NULL,   status varchar(45)DEFAULT NULL,   主要关键(id) )ENGINE = InnoDB AUTO_INCREMENT = 16 DEFAULT CHARSET = latin1;

    INSERT INTO test VALUES(1,' 2011-12-01','待定'),(2,' 2011-12 -02',1,'待定'),(3,' 2011-12-03',1,'完成'),(4, ' 2011-12-04',1,'待定'),(5,' 2011-12-05',1,'完成&# 39;),(6,' 2011-12-06',1,'待定'),(7,' 2011-12-07',1 ,'待定'),(8,' 2011-12-08','待定'),(9,' 2011- 12-09',2,'待定'),(10,' 2011-12-10',2,'等待'),( 11,' 2011-12-11',3,'待定'),(12,' 2011-12-12',4,'完成'),(13,' 2011-12-13','待定'),(14,' 2011-12-14' ,5,'完成'),(15,' 2011-12-15','待定');


    感谢ziesemer提供正确的SELECT查询 - 我从中学到了很多东西。不幸的是,MySQL似乎不允许DELETE使用子查询,所以我转换了ziesemer的答案来改为使用JOINS。但我是一个SQL菜鸟,所以请纠正这些是否可以改进:

    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;
    

    要删除,请将SELECT行替换为:

    DELETE t1 FROM test t1 INNER JOIN test t2
    

2 个答案:

答案 0 :(得分:1)

我已对这些进行了测试,独立工作 - 虽然必须在第一个之后执行第二个以获得您在示例中提供的结果。我很难让它们作为一个Select工作,因为第二个查询取决于第一个完成后表的状态......

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'));

(我会给予其他任何人一个+1的回答可以在一个查询中做到这一点,同时产生相同的,准确的结果 - 我现在很难过。)

答案 1 :(得分:0)

您的第一个问题将通过以下查询解决,只需要进行子选择:

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

对于另一个需要一点思考。 (让我考虑一下)