none
Problema con datos repetidos SQL Server RRS feed

  • Pregunta

  • Se que este tipo de preguntas suelen ser muy comunes, pero me gustaria saber por qué, en la siguiente consulta que les mostraré, obtengo datos que se repiten.

    USE tracking
    SELECT DISTINCT r.id_ruta,U.Nombres, r.fecha, m.telefono, m.modelo,
    'STATUS' = CASE m.estado WHEN 1 THEN 'SI'
    WHEN 2 THEN 'NO'
    END
    FROM ruta_actual as r
    INNER JOIN usuarios AS U ON r.id_ruta = u.id_usuario
    INNER JOIN movil AS M ON u.id_usuario = m.id_ruta
    ORDER BY r.id_ruta

    Siendo este el resultado:

    Que habré hecho mal en la consulta? Quedo atento, gracias :)


    • Editado M4uriXD miércoles, 2 de mayo de 2018 13:30
    miércoles, 2 de mayo de 2018 13:24

Respuestas

  • Bien pero ahi no hay MIN.... si has decidido usar MIN y estas hablando de la tabla M, que son los telefonos, para que no te salgan resultados duplicados de los usuarios que al menos tengan un telefono

    SELECT ruta.fecha, ruta.id_ruta AS RUTA, Us.Nombres AS 'Nombres', MIN(M.modelo) AS 'modelo', 
    'STATUS' =	CASE WHEN MIN(M.estado) = 1 THEN 'SI'
    ELSE 'NO'
    END AS ESTADO, MIN(M.telefono) AS 'Telefono'
    	
    FROM ruta_actual as ruta 		
    
    INNER JOIN  items_tracking AS Items ON Items.id_ruta = ruta.id_ruta
    
    INNER JOIN  movil AS M ON M.id_usuario = Items.id_usuario
    INNER JOIN usuarios AS Us ON Us.id_usuario = ruta.id_ruta
    
    GROUP BY ruta.fecha, ruta.id_ruta, Us.Nombres
    ORDER BY ruta.id_ruta
    
    GO

    De manera que los campos de la tabla M, son los que solo extraes el resultado mas pequeño con la función MIN. y no pueden participar del group by porque si no te los repite.

    Un saludo

    • Marcado como respuesta M4uriXD lunes, 7 de mayo de 2018 17:12
    lunes, 7 de mayo de 2018 15:47

Todas las respuestas

  • Se que este tipo de preguntas suelen ser muy comunes, pero me gustaria saber por qué, en la siguiente consulta que les mostraré, obtengo datos que se repiten.

    Efectivamente, es una consulta muy común.

    La razón por la que se repiten datos cuando usas un JOIN es que el JOIN selecciona todos los posibles emparejamientos de registros entre las tablas que se unen.

    Por ejemplo, si la tabla1 tiene los valores A y B en el campo de unión, y la tabla2 tiene 5 registros con A y otros 5 registros con B en ese campo, el resultado de hacer el JOIN tiene 10 registros (el A de la primera tabla unido con los 5 A de la segunda, y lo mismo con el B). Esto implica que el resto delos campos de la tabla A tienen 5 repeticiones (una por cada registro de B que se unió a ese mismo registro de A).

    miércoles, 2 de mayo de 2018 13:36
  • Pero ese es el tema en mi caso quizás hice mal la relación en el JOIN porque no debería mostrarme ningún dato repetido. Ahora probé de esta manera y obtuve menos datos repetidos, pero algunos ID_Ruta no los muestra.

    USE tracking
    SELECT DISTINCT Ruta.id_ruta AS RUTA, Us.Nombres, M.modelo, 
    'STATUS' =	CASE M.estado WHEN 1 THEN 'SI'
    WHEN 2 THEN 'NO'
    END, M.telefono
    	
    	FROM ruta_actual as ruta 
    		
    	INNER JOIN usuarios AS Us ON Us.id_usuario = id_ruta
    	INNER JOIN  items_tracking AS Items ON Items.id_ruta = ruta.id_ruta
    	INNER JOIN  movil AS M ON M.id_usuario = Items.id_usuario
    
    GROUP BY Items.imei, Nombres, Ruta.id_ruta, m.modelo, M.estado, M.telefono
    GO

    Quedando así al final:

    • Editado M4uriXD miércoles, 2 de mayo de 2018 15:17
    miércoles, 2 de mayo de 2018 14:53
  • Lo de "ON Us.id_usuario = id_ruta" tiene bastante mal aspecto. Una de dos: o estan fatal elegidos los nombres de los campos, o estas uniendo por un campo incorrecto.
    miércoles, 2 de mayo de 2018 15:24
  • Si puede que tengas razón ese id_ruta corresponde a mi tabla ruta_actual, lo revisaré
    miércoles, 2 de mayo de 2018 16:00
  • No hay resultados repetidos,el distinct funciona bien el tema es que para que el distinct traiga un solo renglon TODOS los campos deben ser iguales,aca te trae un solo registro por cada combinacion,en algunos casos es el status,en otra el modelo.

    Proba a sacarle el distinct y te va a traer mas filas.

    Si no tenes que pedir solo los campos que puedan agruparse mejor.

    create table #tmp1(id int,descr varchar(max))
    insert into #tmp1 select 1,1
    insert into #tmp1 select 2,2
    creATE TABLE #TMP2 (ID INT)
    INSERT INTO #TMP2 SELECT 1
    INSERT INTO #TMP2 SELECT 1
    INSERT INTO #TMP2 SELECT 2
    SELECT * FROM #TMP1
    SELECT * FROM #TMP2
    SELECT A.ID,A.DESCR,B.ID FROM #TMP1 A INNER JOIN #TMP2 B ON A.ID = B.ID ORDER BY A.ID
    SELECT DISTINCT A.ID,A.DESCR,B.ID FROM #TMP1 A INNER JOIN #TMP2 B ON A.ID = B.ID ORDER BY A.ID

    jueves, 3 de mayo de 2018 23:38
  • Hola M4uriXd:

    No has hecho nada mal, y no se repiten los datos a tenor de las capturas que has realizado.

    El problema radica, en que los usuarios tienen varios telefonos, por tanto te muestra la fila de los detalles del usuario y si el usuario tiene dos telefonos, dos filas....

    En cuanto al uso de distinct y group by, tienes que considerar:

    El uso de distinct, empeora el rendimiento, por tanto si lo puedes evitar, mejor.

    El uso de group by cuando todas las columnas se mencionan en el group by y sin ningún tipo de funcion de agrupamiento no te va a realizar nada.

    ¿Que datos consideras que estan repetidos?

    ejemplo si lo que quieres hacer es obtener la fila de

    2 YANA XPERIA SA 999999 y 00 NA 999

    RUTA.ID_RUTA, US.NOMBRES, N.MODELO, M.ESTADO, M.TELEFONO y si tienes mas N.MODELO2, M.ESTADO2, M.TELEFONO2, M.MODELO3, M.ESTADO3, M.TELEFONO3.....

    Esto se llama pivot dinámico, son sentencias complicadas de realizar.

    https://msdn.microsoft.com/es-es/communitydocs/servidores/sql-server/pivot-dinamico

    Por el contrario si solo tienes por ejemplo como máximo 3 número de telefono, se puede hacer un pivot estatico. Es más fácil, de entender.

    http://devtroce.com/2013/05/28/pasar-filas-a-columnas-con-pivot-en-sql-server/

    Y si solo quieres una fila con un telefono aunque tenga 2 o tres, tienes que escoger, y que el telefono sea el por ejemplo MIN(M.TELEFONO)

    https://docs.microsoft.com/es-es/sql/t-sql/functions/aggregate-functions-transact-sql?view=sql-server-2017

    Un saludo

    • Marcado como respuesta M4uriXD sábado, 5 de mayo de 2018 20:34
    • Desmarcado como respuesta M4uriXD lunes, 7 de mayo de 2018 13:17
    sábado, 5 de mayo de 2018 6:54
  • Gracias, muchas gracias! Era lo que buscaba mostrar solo un valor, aunque el mismo campo tuviese mas valores distintos. :)
    sábado, 5 de mayo de 2018 20:34
  • Puedes usar Distinct, 
    sábado, 5 de mayo de 2018 21:18
  • Lo probe usando MIN pero no cambio nada
    lunes, 7 de mayo de 2018 13:17
  • Estimado M4uriXD:

    Que has probado usando MIN. Para poder resolver una consulta SQL, creo que tienes que mejorar, mucho, tu precisión con la información.

    USE tracking
    SELECT DISTINCT Ruta.id_ruta AS RUTA, Us.Nombres, M.modelo, 
    'STATUS' =	CASE M.estado WHEN 1 THEN 'SI'
    WHEN 2 THEN 'NO'
    END, MIN(M.telefono)/* ESTO DEBIERA DE SER TU MIN POR EJEMPLO */
    	
    	FROM ruta_actual as ruta 
    		
    	INNER JOIN usuarios AS Us ON Us.id_usuario = id_ruta
    	INNER JOIN  items_tracking AS Items ON Items.id_ruta = ruta.id_ruta
    	INNER JOIN  movil AS M ON M.id_usuario = Items.id_usuario
    
    GROUP BY Items.imei, Nombres, Ruta.id_ruta, m.modelo, M.estado /*HAY QUE SACARLO DEL GROUP BY */

    ¿esta es tú Consulta?

    lunes, 7 de mayo de 2018 13:52
  • Si disculpa, si esta es:

    SELECT ruta.fecha, ruta.id_ruta AS RUTA, Us.Nombres AS 'Nombres',  M.modelo AS 'modelo', 
    'STATUS' =	CASE M.estado WHEN 1 THEN 'SI'
    WHEN 2 THEN 'NO'
    END, M.telefono AS 'Telefono'
    	
    FROM ruta_actual as ruta 		
    
    INNER JOIN  items_tracking AS Items ON Items.id_ruta = ruta.id_ruta
    
    INNER JOIN  movil AS M ON M.id_usuario = Items.id_usuario
    INNER JOIN usuarios AS Us ON Us.id_usuario = ruta.id_ruta
    
    GROUP BY ruta.fecha, ruta.id_ruta, Us.Nombres,  M.modelo,M.estado,M.telefono
    ORDER BY ruta.id_ruta
    
    GO

    Aunque el group by lo puse porque me arrojaba error si no lo tenia, y si quito un campo del 'group by' me arroja un error también, algo como esto:

    'La columna - M.Estado - de la lista de seleccion no es valida porque no esta contenida en una funcion de agregado ni en la clausula GROUP BY'

    • Editado M4uriXD lunes, 7 de mayo de 2018 14:24
    lunes, 7 de mayo de 2018 14:21
  • Bien pero ahi no hay MIN.... si has decidido usar MIN y estas hablando de la tabla M, que son los telefonos, para que no te salgan resultados duplicados de los usuarios que al menos tengan un telefono

    SELECT ruta.fecha, ruta.id_ruta AS RUTA, Us.Nombres AS 'Nombres', MIN(M.modelo) AS 'modelo', 
    'STATUS' =	CASE WHEN MIN(M.estado) = 1 THEN 'SI'
    ELSE 'NO'
    END AS ESTADO, MIN(M.telefono) AS 'Telefono'
    	
    FROM ruta_actual as ruta 		
    
    INNER JOIN  items_tracking AS Items ON Items.id_ruta = ruta.id_ruta
    
    INNER JOIN  movil AS M ON M.id_usuario = Items.id_usuario
    INNER JOIN usuarios AS Us ON Us.id_usuario = ruta.id_ruta
    
    GROUP BY ruta.fecha, ruta.id_ruta, Us.Nombres
    ORDER BY ruta.id_ruta
    
    GO

    De manera que los campos de la tabla M, son los que solo extraes el resultado mas pequeño con la función MIN. y no pueden participar del group by porque si no te los repite.

    Un saludo

    • Marcado como respuesta M4uriXD lunes, 7 de mayo de 2018 17:12
    lunes, 7 de mayo de 2018 15:47
  • Si es cierto en esa consulta no coloque la función MIN() y probé aquella consulta. La modifique un poco y al final funcionó muy bien. Gracias :)
    lunes, 7 de mayo de 2018 17:12