Удалить дочерние записи, если число превышает 10

0

У меня есть отношение parent-child для следующих таблиц:

CREATE TABLE 'pages' (
    id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(100) NULL,
    PRIMARY KEY ( id )
)

CREATE TABLE 'pageObjects' (
    id INT NOT NULL AUTO_INCREMENT,
    object TEXT NULL,
    lastChanged TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL,
    fkPageId int NOT NULL,
    PRIMARY KEY ( id )
)

pages имеют отношение one: many к pageObjects.

Всякий раз, когда записи pageObjects подключенные к одной странице, превышают 10, все записи, отредактированные в прошлом и превышающие 10, должны быть удалены.

Я хотел сделать это в одном запросе, но я не могу понять это...

Вот как далеко я получил:

DELETE 
FROM pageObjects
WHERE id NOT IN (
    SELECT po.id, po.fkPageId FROM (
        SELECT objects.fkPageId FROM (
            SELECT COUNT(*) as count, fkPageId
            FROM pageObjects
            GROUP BY fkPageId
        ) objects
        WHERE count > 10
    ) AS page
    JOIN pageObjects po 
    ON page.fkPageId = po.fkPageId
    AND po.lastChanged  < (
        SELECT MIN(lastChanged )
        FROM pageObjects
        WHERE fkPageId = po.fkPageId
        GROUP BY fkPageId
        ORDER BY lastChanged  DESC
        LIMIT 10
    )
)

К сожалению, бит LIMIT в нижнем подзапросе не работает так, как я хочу, потому что функция MIN() должна применяться после того, как применяется LIMIT.

Поэтому я пробовал:

DELETE 
FROM pageObjects
WHERE id NOT IN (
    SELECT po.id, po.fkPageId FROM (
        SELECT objects.fkPageId FROM (
            SELECT COUNT(*) as count, fkPageId
            FROM pageObjects
            GROUP BY fkPageId
        ) objects
        WHERE count > 10
    ) AS page
    JOIN pageObjects po 
    ON page.fkPageId = po.fkPageId
    AND po.lastChanged  < (
        SELECT MIN(lastChanged)
        FROM (  
            SELECT lastChanged
            FROM pageObjects
            WHERE fkPageId = po.fkPageId
            GROUP BY fkPageId
            ORDER BY lastChanged DESC
            LIMIT 10
        )
    )
)

Но это невозможно, потому что po.fkPageId недоступен в подзапросе подзапроса.

Есть ли способ сделать это вот так?

Теги:

1 ответ

1
Лучший ответ

Вы можете сделать это достаточно просто, посчитав количество последних записей для каждого идентификатора:

DELETE FROM pageObjects
WHERE id IN (
  SELECT id FROM pageObjects po
  WHERE (
    SELECT count(id) 
    FROM pageObjects po2 
    WHERE po2.fkPageId = po.fkPageId
    AND po2.lastChanged > po.lastChanged
  ) > 10
)

Проверьте, что возвращает выбор: http://www.sqlfiddle.com/#!9/f5218f/1/0

  • 0
    Это прекрасно работает. Что вы делаете здесь, так это получаете все записи старше 10 записей одного уровня, верно? Очень хорошо. Спасибо за понимание!
  • 0
    Да, на месте. Удаляя все записи с более чем 10 младшими братьями и сестрами, вы по сути остаетесь только с последними 10.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню