2011-08-22 23 views
7

Tengo un sistema de lista de seguimiento que he codificado, en la vista general de la lista de observación de los usuarios, verían una lista de registros, sin embargo, la lista muestra duplicados cuando en la base de datos solo muestra el número exacto y correctoGROUP BY no elimina los duplicados

He intentado GROUP BY watch.watch_id, GROUP BY rec.record_id, ninguno de los tipos de grupo que he probado parece eliminar duplicados. No estoy seguro de lo que estoy haciendo mal.

mesa
SELECT watch.watch_date, 
     rec.street_number, 
     rec.street_name, 
     rec.city, 
     rec.state, 
     rec.country, 
     usr.username 
FROM 
(
    watchlist watch 

    LEFT OUTER JOIN records rec ON rec.record_id = watch.record_id 

    LEFT OUTER JOIN members usr ON rec.user_id = usr.user_id 
) 
WHERE watch.user_id = 1 
GROUP BY watch.watch_id 
LIMIT 0, 25 

La lista se parece a esto:

+----------+---------+-----------+------------+ 
| watch_id | user_id | record_id | watch_date | 
+----------+---------+-----------+------------+ 
|  13 |  1 |  22 | 1314038274 | 
|  14 |  1 |  25 | 1314038995 | 
+----------+---------+-----------+------------+ 

Respuesta

17

GROUP BY no "eliminar duplicados". GROUP BY permite la agregación. Si todo lo que quiere es combinar filas duplicadas, use SELECT DISTINCT.

Si necesita combinar filas que están duplicadas en algunas columnas, use GROUP BY, pero debe especificar qué hacer con las otras columnas. Puede omitirlos (al no incluirlos en la cláusula SELECT) o agregarlos (utilizando funciones como SUM, MIN y AVG). Por ejemplo:

SELECT watch.watch_id, COUNT(rec.street_number), MAX(watch.watch_date) 
... GROUP by watch.watch_id 

EDITAR

El PO pide algunas aclaraciones.

Considere la "vista" - todos los datos reunidos por los FROM y JOINs y los WHEREs - llame a ese V. Hay dos cosas que podría querer hacer.

En primer lugar, es posible que tenga filas completamente duplicados que desea combinar:

a b c 
- - - 
1 2 3 
1 2 3 
3 4 5 

Entonces sólo tiene que utilizar DISTINCT

SELECT DISTINCT * FROM V; 

a b c 
- - - 
1 2 3 
3 4 5 

O bien, es posible que tenga filas parcialmente duplicados que desea combinar:

a b c 
- - - 
1 2 3 
1 2 6 
3 4 5 

Esas dos primeras filas son "iguales" en algún sentido, pero claramente diferentes en otro sentido (en particular, se combinarían no por SELECT DISTINCT). Tienes que decidir cómo combinarlos. Se podía descartar la columna C como poco importante:

SELECT DISTINCT a,b FROM V; 

a b 
- - 
1 2 
3 4 

O usted podría realizar algún tipo de agregación en ellos. Se podría sumarlos:

SELECT a,b, SUM(c) "tot" FROM V GROUP BY a,b; 

a b tot 
- - --- 
1 2 9 
3 4 5 

Se podría añadir escoger el valor más pequeño:

SELECT a,b, MIN(c) "first" FROM V GROUP BY a,b; 

a b first 
- - ----- 
1 2 3 
3 4 5 

O se puede tomar la media (AVG), la desviación estándar (STD), y cualquiera de un grupo de otras funciones que toman un grupo de valores para c y los combinan en uno.

Lo que no es realmente una opción es simplemente no hacer nada. Si solo enumera las columnas desagrupadas, el DBMS lanzará un error (Oracle lo hace - la opción correcta, imo) o escogerá un valor más o menos al azar (MySQL). Pero como Dr.Peart dijo: "Cuando eliges no decidir, todavía has hecho una elección".

+0

Disculpe, podría aclarar un poco más con la agregación. – MacMac

+0

Veo, una pregunta, ¿cómo puede seleccionar las columnas con 'DISTINCT' en lugar de' DISTINCT * '. – MacMac

+0

Releer. Ya hay un ejemplo en mi respuesta. – Malvolio

0

Usted está agrupando por watch.watch_id y tiene dos resultados, que tienen identificadores de reloj diferentes, por lo que, naturalmente, no se agrupan.

Además, de los resultados mostrados tienen diferentes registros. Eso parece ser un resultado esperado perfectamente válido. Si está intentando solo seleccionar valores distintos, entonces no desea ot GROUP, pero desea seleccionar por valores distintos.

SELECT DISTINCT() ...

3

Mientras SELECT DISTINCT efecto, puede trabajar en su caso, es importante tener en cuenta la razón por lo que tiene no está funcionando.

Está seleccionando campos que están fuera del GROUP BY. Aunque MySQL permite esto, las filas exactas que devuelve para los campos que no son GROUP BY no están definidas.

Si quería hacer esto con un GROUP BY a intentar algo más parecido a lo siguiente:

SELECT watch.watch_date, 
     rec.street_number, 
     rec.street_name, 
     rec.city, 
     rec.state, 
     rec.country, 
     usr.username 
FROM 
(
    watchlist watch 

    LEFT OUTER JOIN est8_records rec ON rec.record_id = watch.record_id 

    LEFT OUTER JOIN est8_members usr ON rec.user_id = usr.user_id 
) 
WHERE watch.watch_id IN (
SELECT watch_id FROM watch WHERE user_id = 1 
GROUP BY watch.watch_id) 
LIMIT 0, 25 
+0

Me aparece 'Esta versión de MySQL aún no admite 'LIMIT & IN/ALL/ANY/ALGUNA subconsulta'. – MacMac

+0

Lo siento, quise poner eso fuera de la subconsulta. Ver actualización –

0

Si dice que su mesa lista es única, entonces uno (o ambos) de las otras mesas ya sea (a) tiene duplicados, o (b) no es exclusivo de la clave que está utilizando.

Para suprimir duplicados en los resultados, ya sea para uso distinto como dice @Laykes, o tratar

GROUP BY watch.watch_date, 
     rec.street_number, 
     rec.street_name, 
     rec.city, 
     rec.state, 
     rec.country, 
     usr.username 

De alguna manera suena como usted espera que los 3 mesas sean únicos por sus llaves, sin embargo. Si ese es el caso, simplemente está enmascarando algún otro problema con su SQL tratando de recuperar valores distintos.

1

I Nunca recomendaría usar SELECT DISTINCT, es realmente lento en grandes conjuntos de datos.

Intente utilizar cosas como EXISTS.