Nice programing

하위 쿼리를 조건으로 사용하는 MySQL DELETE FROM

nicepro 2020. 10. 17. 12:21
반응형

하위 쿼리를 조건으로 사용하는 MySQL DELETE FROM


다음과 같은 쿼리를 시도하고 있습니다.

DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (
    SELECT DISTINCT(th1.tid)
    FROM term_hierarchy AS th1
    INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
    WHERE th1.parent = 1015
);

알 수 있듯이 동일한 tid에 다른 부모가있는 경우 1015에 대한 부모 관계를 삭제하고 싶습니다. 그러나 구문 오류가 발생합니다.

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS th
WHERE th.parent = 1015 AND th.tid IN (
  SELECT DISTINCT(th1.tid)
  FROM ter' at line 1

문서를 확인하고 하위 쿼리를 자체적으로 실행했는데 모두 확인한 것 같습니다. 아무도 여기서 무엇이 잘못되었는지 알아낼 수 있습니까?

업데이트 : 아래에 답변했듯이 MySQL은 삭제하려는 테이블을 조건에 대한 하위 쿼리에 사용하는 것을 허용하지 않습니다.


삭제할 대상 테이블을 지정할 수 없습니다.

해결 방법

create table term_hierarchy_backup (tid int(10)); <- check data type

insert into term_hierarchy_backup 
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015;

DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (select tid from term_hierarchy_backup);

하위 쿼리를 사용하는 동안 삭제하려는이 질문을 찾는 다른 사람들을 위해 MySQL을 능가하는이 예제를 남깁니다 (일부 사람들은 수행 할 수 없다고 생각하더라도).

DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
             FROM tableE
             WHERE arg = 1 AND foo = 'bar');

오류가 발생합니다.

ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause

그러나이 쿼리 :

DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
             FROM (SELECT id
                   FROM tableE
                   WHERE arg = 1 AND foo = 'bar') x);

잘 작동합니다.

Query OK, 1 row affected (3.91 sec)

하위 쿼리를 추가 하위 쿼리 (여기서는 x라고 함)로 감싸면 MySQL은 사용자가 요청한대로 기꺼이 처리합니다.


별칭은 DELETE키워드 뒤에 포함되어야합니다 .

DELETE th
FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN 
(
    SELECT DISTINCT(th1.tid)
    FROM term_hierarchy AS th1
    INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
    WHERE th1.parent = 1015
);

다음과 같이 delete 문에서 별칭을 다시 참조해야합니다.

DELETE th FROM term_hierarchy AS th
....

여기 MySQL 문서에 설명되어 있습니다.


나는 이것에 약간 다른 방식으로 접근했고 그것은 나를 위해 일했습니다.

더 이상 조건 행이 남아 있지 않은 secure_links테이블을 참조하는 conditions테이블에서 제거해야했습니다 . 기본적으로 하우스 키핑 스크립트입니다. 이로 인해 오류가 발생했습니다. 삭제할 대상 테이블을 지정할 수 없습니다.

그래서 여기에서 영감을 얻기 위해 아래 쿼리를 생각 해냈고 잘 작동합니다. 이는 sl1DELETE에 대한 참조로 사용되는 임시 테이블 생성하기 때문 입니다.

DELETE FROM `secure_links` WHERE `secure_links`.`link_id` IN 
            (
            SELECT
                `sl1`.`link_id` 
            FROM 
                (
                SELECT 

                    `sl2`.`link_id` 

                FROM 
                    `secure_links` AS `sl2` 
                    LEFT JOIN `conditions` ON `conditions`.`job` = `sl2`.`job` 

                WHERE 

                    `sl2`.`action` = 'something' AND 
                    `conditions`.`ref` IS NULL 
                ) AS `sl1`
            )

나를 위해 작동합니다.


Isn't the "in" clause in the delete ... where, extremely inefficient, if there are going to be a large number of values returned from the subquery? Not sure why you would not just inner (or right) join back against the original table from the subquery on the ID to delete, rather than us the "in (subquery)".?

DELETE T FROM Target AS T
RIGHT JOIN (full subquery already listed for the in() clause in answers above) ` AS TT ON (TT.ID = T.ID)

And maybe it is answered in the "MySQL doesn't allow it", however, it is working fine for me PROVIDED I make sure to fully clarify what to delete (DELETE T FROM Target AS T). Delete with Join in MySQL clarifies the DELETE / JOIN issue.


If you want to do this with 2 queries, you can always do something similar to this:

1) grab ids from the table with:

SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ...

Then copy result with mouse/keyboard or programming language to XXX below:

2) DELETE FROM your_table WHERE id IN ( XXX )

Maybe you could do this in one query, but this is what I prefer.


@CodeReaper, @BennyHill: It works as expected.

However, I wonder the time complexity for having millions of rows in the table? Apparently, it took about 5ms to execute for having 5k records on a correctly indexed table.

My Query:

SET status = '1'
WHERE id IN (
    SELECT id
    FROM (
      SELECT c2.id FROM clusters as c2
      WHERE c2.assign_to_user_id IS NOT NULL
        AND c2.id NOT IN (
         SELECT c1.id FROM clusters AS c1
           LEFT JOIN cluster_flags as cf on c1.last_flag_id = cf.id
           LEFT JOIN flag_types as ft on ft.id = cf.flag_type_id
         WHERE ft.slug = 'closed'
         )
      ) x)```

Or is there something we can improve on my query above?

참고URL : https://stackoverflow.com/questions/4471277/mysql-delete-from-with-subquery-as-condition

반응형