2010-12-30 11 views
61

Este código no funciona para MySQL 5.0, la forma de volver a escribir para que funcione¿Cómo borrar de seleccionar en MySQL?

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

Quiero borrar columnas que no dispongamos de identificación única. Agregaré que la mayoría de las veces es solo una identificación (probé la sintaxis y tampoco funciona).

Respuesta

144

SELECT (sub) consultas devuelve el resultado conjuntos. Por lo tanto, debe usar IN, no = en su cláusula WHERE.

Además, como se muestra en this answer, no puede modificar la misma tabla desde una subconsulta dentro de la misma consulta. Sin embargo, usted puede entonces SELECTDELETE en consultas separadas, o nido de otra subconsulta y alias el resultado subconsulta interior (parece bastante hacky, sin embargo):

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

O usar combinaciones as suggested by Mchl.

+1

que tenía una mesa con 150 llaves duplicadas. Ejecuté la consulta anterior y decía "144 filas afectadas", pero todavía había claves duplicadas. Así que ejecuté la consulta nuevamente y dice 5 filas afectadas, nuevamente: 1 fila afectada. Luego todas las llaves duplicadas desaparecieron. ¿Por qué es esto? – Alex

+0

Esto está sucediendo, porque solo está eliminando 1 entrada de cada conjunto de duplicados: 'SELECT id DESDE mensajes GROUP BY id TIENE (COUNT (id)> 1)' – havvg

+0

# 1248 - Cada tabla derivada debe tener su propio 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

Esto parece funcionar, pero estoy confundido por la sintaxis y no puedo encontrar ningún recurso en otro lugar para explicarlo. 'CROSS JOIN' aparentemente realiza una unión cartesiana, por lo que parece que podría hacer un trabajo innecesario o funcionar de manera subóptima. ¿Alguien podría explicar? – wintron

+0

Hará un producto cartesiano solo si no hay una cláusula 'USING'. Con 'USING', el producto está limitado a pares con el mismo valor en la columna' id', por lo que es muy limitado. – Mchl

+1

Impresionante solución. –

-1

Si desea eliminar todos los duplicados, pero uno de cada conjunto de duplicados, esta es una solución:

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

puede utilizar combinación interna:

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