выбрать и удалить строки в группах, используя MySQL - PullRequest
2 голосов
/ 24 декабря 2011

Я видел примеры для манипулирования дублирующимися строками, но я не могу понять, как отобразить их, чтобы решить мою проблему.

+----+------------+------+---------+
| 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. Мне нужно сначала выбрать / удалить любую строку, где status = 'Pending', а ее дата старше самой молодой даты для любой строки, где status = 'Done'. Например, это будет выбирать / удалять строки с идентификаторами 1, 2, 4 и 13.

  2. Мне нужно затем выбрать / удалить любую строку, где status = 'Pending', и это не самая старая дата, где status = 'Pending'. Например, это будет выбирать / удалять строки с идентификаторами 7, 8 и 10.

Полученная таблица:

+----+------------+------+---------+
| 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 CHARSET ПО УМОЛЧАНИЮ = latin1;

INSERT INTO test VALUES (1, '2011-12-01', 1, 'Pending'), (2, '2011-12-02', 1, 'Pending'), (3, '2011 -12-03 ', 1, «Готово»), (4, «2011-12-04», 1, «В ожидании»), (5, «2011-12-05», 1, «Готово»), ( 6, «2011-12-06», 1, «В ожидании»), (7, «2011-12-07», 1, «В ожидании»), (8, «2011-12-08», 1, «В ожидании» '), (9,' 2011-12-09 ', 2,' В ожидании '), (10,' 2011-12-10 ', 2,' В ожидании '), (11,' 2011-12-11 ', 3, «В ожидании»), (12, «2011-12-12», 4, «Готово»), (13, «2011-12-13», 5, «В ожидании»), (14, «2011-12» -14 ', 5,' Готово '), (15,' 2011-12-15 ', 5,' Ожидание ');


Спасибо 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 ]

1 голос
/ 24 декабря 2011

У меня есть эти тесты, работающие независимо - хотя 2-й должен выполняться после 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 любому, кто ответит, может сделать это в одном запросе, при этом получая такие же точные результаты - пока что я в тупике.)

0 голосов
/ 24 декабря 2011

Ваша первая проблема будет решена с помощью приведенного ниже запроса, просто вам нужно выполнить подвыбор:

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

, для другой нужно немного подумать.(дай мне подумать)

...