2010-12-30 7 views
61

Ten kod nie działa na MySQL 5.0, jak re-write to, aby pracowaćJak usunąć z wybierz w MySQL?

DELETE FROM posts where id=(SELECT id FROM posts GROUP BY id HAVING (COUNT(id) > 1)) 

Chcę usunąć kolumny, które nie mają niepowtarzalny identyfikator. Dodam, że przez większość czasu jest to tylko jeden identyfikator (próbowałem składni i nie działa również).

Odpowiedz

144

SELECT (pod) zapytania zwracają wynik ustawia. Więc musisz użyć IN, a nie = w swoim klauzuli WHERE.

Ponadto, jak pokazano w this answer, nie można modyfikować tej samej tabeli z podzapytania w ramach tego samego zapytania. Jednakże, można albo SELECT następnie DELETE w oddzielnych zapytań lub gniazdo inny alias podzapytania i wewnętrzna wynik podzapytania (wygląda raczej hacky, choć):

DELETE FROM posts WHERE id IN (
    SELECT * FROM (
     SELECT id FROM posts GROUP BY id HAVING (COUNT(id) > 1) 
    ) AS p 
) 

lub użyj łączy as suggested by Mchl.

+1

miałem tabela ze 150 zduplikowanymi kluczami. Wykonałem powyższe zapytanie i napisałem "dotyczyło 144 wierszy", ale tam nadal zduplikowano klucze. W związku z tym ponownie wykonałem kwerendę i 5 błędnie przeanalizowanych wierszy ponownie: 1 wiersz dotyczy. Następnie wszystkie duplikaty kluczy zniknęły. Dlaczego to? – Alex

+0

To się dzieje, ponieważ usuwane są tylko 1 wpis z każdego zestawu duplikatów: "WYBIERZ ID ZE WIADOMOŚCI GROUP BY ID HAVING (COUNT (identyfikator)> 1)' – havvg

+0

# 1248 - Każda wyprowadzona tabela musi mieć własny alias – thang

19
DELETE 
    p1 
    FROM posts AS p1 
CROSS JOIN (
    SELECT ID FROM posts GROUP BY id HAVING COUNT(id) > 1 
) AS p2 
USING (id) 
+0

Wygląda na to, że działa, ale jestem zdezorientowany przez składnię i nie mogę znaleźć żadnych zasobów gdzie indziej, aby to wyjaśnić. "CROSS JOIN" najwyraźniej wykonuje kartezjańskie połączenie, więc wydaje się, że może to zrobić niepotrzebną pracę lub wykonać suboptymalnie? Czy ktoś mógłby wyjaśnić? – wintron

+0

Wykona produkt kartezjański tylko wtedy, gdy nie ma klauzuli "USING". Przy "UŻYWANiu" produkt jest ograniczony do par o tej samej wartości w kolumnie "id", więc w rzeczywistości jest bardzo ograniczony. – Mchl

+1

Niesamowite rozwiązanie. –

-1

Jeśli chcesz usunąć wszystkie duplikaty, ale jednym z każdego zestawu duplikatów, jest to jedno rozwiązanie:

DELETE posts 
FROM posts 
LEFT JOIN (
    SELECT id 
    FROM posts 
    GROUP BY id 
    HAVING COUNT(id) = 1 

    UNION 

    SELECT id 
    FROM posts 
    GROUP BY id 
    HAVING COUNT(id) != 1 
) AS duplicate USING (id) 
WHERE duplicate.id IS NULL; 
2

można użyć sprzężenia wewnętrznego:

DELETE 
    ps 
FROM 
    posts ps INNER JOIN 
     (SELECT 
      distinct id 
     FROM 
      posts 
     GROUP BY id 
     HAVING COUNT(id) > 1) dubids on dubids.id = ps.id