Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   MySQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=21)
-   -   Cómo utilizar consultas con DISTINCT de forma correcta (https://www.clubdelphi.com/foros/showthread.php?t=33934)

dec 21-07-2006 01:19:29

Cómo utilizar consultas con DISTINCT de forma correcta
 
Hola,

Salud para todos. Me encuentro con un problema al tratar de llevar a cabo cierta consulta en MySQL trabajando con PHP. El objetivo de la consulta es obtener una serie de registros sin duplicar y para ello la escribo como sigue:

Código PHP:

$consultaSql "SELECT DISTINCT enlaces.url, enlaces.titulo, enlaces.fecha, 
                 enlaces.descripcion, enlaces.etiquetas, usuarios.login 
                  FROM enlaces, usuarios"


La intención de la consulta es, como digo, que retorne una serie de registros (enlaces) que no estén duplicados. El problema viene dado (por lo poco que he averiguado sobre DISTINCT) al incluir también en el SELECT un campo perteneciente a otra tabla.

Como el DISTINCT se realiza sobre los campos incluidos en el SELECT, resulta que la consulta al cabo retorna enlaces repetidos, porque los usuarios de los enlaces no están repetidos... ¿se comprende? Esta consulta funciona tal como se espera:

Código PHP:

$consultaSql "SELECT DISTINCT enlaces.url, enlaces.titulo, enlaces.fecha, 
                 enlaces.descripcion, enlaces.etiquetas 
                  FROM enlaces"


O sea, retorna enlaces sin duplicar, cuyos campos especificadosen el SELECT no sean iguales. Pero, entonces estoy en un problema... porque según mi lógica (pobre, de diez duros) sería bien que dicha cosulta me retornara también los nombres de los usuarios, porque estos son como los "dueños" de los enlaces, y, junto a la información de cada enlace quisiera mostrar a su dueño.

Lo que se me ocurre (el no va más) es incluir en la consulta anterior el campo "id_usuario" conque cuenta cada enlace, y, luego, para cada enlace, buscar el "nombre" del usuario correspondiente a ese "id_usuario",... pero, claro está, si hay cien enlaces... significarían cien consultas a la base de datos... y esto no tiene mucho sentido, porque a más enlaces más consultas... algo que no concuerda demasiado, ¿no os parece?

En fin. Maestros del SQL, licenciados en PHP, iniciados en DISCINCT y sabios en general, ¿qué puedo hacer? ¿pido un imposible? ¿se me está escapando alguna cosa? Seguro. Muchas gracias de antemano por cuanto podáis decir al respecto. :)

Mick 21-07-2006 04:11:06

Creo que lo estas enfocando mal, para hacer lo que quieres te basta hacer un left join o un inner join. Si no entiendo mal quieres mostrar una lista de enlaces junto con el usuario que creo cada enlace. Asi que con algo como:

Código:

SELECT url,titulo,fecha,usuarios.login
FROM enlaces
LEFT JOIN usuarios
ON enlaces.id_usuario = usuarios.id_usuario

He supuesto que en la tabla usuarios habra un campo id_usuario igual que en la tabla de enlaces, si el nombre que le has dado a ese campo no es ese corrige la sentencia sql e indica el nombre correcto.

Pillate un manual de sql y mirate los distintos tipos de JOINS que existen y en que casos se usan.

Saludos

dec 21-07-2006 04:53:28

Hola,

Bueno. El objetivo de que no se retornen enlaces duplicados sí que parece que puedo conseguirlo de este modo:

Código SQL [-]
SELECT DISTINCT enlaces.url
FROM loturak.enlaces
LEFT JOIN loturak.usuarios
ON enlaces.id_usuario = usuarios.id


Pero, la consulta no cumple con mis espectativas (otra cosa será que estas sean disparatadas, que pueden serlo). No obtengo con dicha consulta el "login" del usuario (de la tabla "usuarios"), y, en cuanto trato de hacerlo:

Código SQL [-]
SELECT DISTINCT usuarios.login, enlaces.url
FROM loturak.enlaces
LEFT JOIN loturak.usuarios
ON enlaces.id_usuario = usuarios.id

La consulta retorna el "login", pero, también enlaces duplicados... Bueno. En todo caso muchas gracias por responder Mick. Es muy posible que leyendo sobre lo que dices pudiera pensar de otro modo el problema.

dec 21-07-2006 05:28:26

Hola,

Definitivamente tengo mucho que aprender de MySQL y de SQL en general como para ponerme a hacer mis pinitos como estoy intentando. Por las pruebas que he hecho me parece que el planteamiento del problema no es correcto.

Porque cuando digo que la consulta devuelve registros duplicados (que es lo que trato de evitar) estoy faltando a la realidad. Lo que a mí me parecían registros duplicados en realidad no lo son: y no lo son porque DISTINCT funciona, claro está.

Supuesta esta consulta:

Código SQL [-]
SELECT DISTINCT login, url FROM usuarios, enlaces

No sé porqué tendía a pensar que los registros que obtenía eran duplicados, cuando no es así. Me explicaré de una vez. En la base de datos en que estoy probando todo esto existen tres usuarios. Cada usuario tiene seis enlaces, pero, y aquí está el meollo, son enlaces repetidos, que a modo de prueba inserté en la base de datos.

Así que, el resultado de la anterior consulta podría ser este:

Código:

login ---------------- url

betatester1 ---------- http://www.google.com/
betatester1 ---------- http://www.clubdelphi.com/
betatester2 ---------- http://www.google.com/
betatester2 ---------- http://www.clubdelphi.com/

Efectivamente, si miramos las URL de los enlaces vemos que se repiten, pero, los registros que devuelve la consulta no están duplicados: lo que ocurre es que distintos usuarios han añadido los mismos enlaces.

No sé. Debería pensar en dedicarme a otra cosa, qué sé yo, a la pesca del cangrejo hermitaño, con todos mis respetos para el cangrejo hermitaño, que no me lo pondrá fácil además.

Ahora mismo dudo, simplemente. ¿Se supone que no debo dejar ingresar en la base de datos los mismos enlaces por distintos usuarios? ¿Pero no es esto absurdo? Acaso podría mirarse porque un usuario no duplicara un enlace previamente insertado por el mismo, pero, ¿porqué no va a poder insertar un enlace que ya hubiera insertado otro usuario?

Son usuarios distintos... se supone que para algo, y, entre otras cosas, para mantener dos apartados distintos en la aplicación Web, con la posibilidad de añadir enlaces, sus enlaces, con independencia de los otros usuarios...

Me estoy liando. Me voy por las ramas porque veo que ando más perdido y ofuscado que un pulpo en un garaje, como suele decirse. :o Lo mismo tengo que replantearme (o mejor dicho, plantearme por primera vez) menos a la ligera las tablas que han de componer la aplicación, sus correspondientes campos y relaciones con otras tablas, etc., etc., etc.

Emilio 21-07-2006 11:13:00

Prueba con esto...
Código SQL [-]
SELECT DISTINCT login, url FROM usuarios, enlaces GROUP BY url

dec 21-07-2006 23:25:56

Hola,

Gracias Emilio. Lo que pasa es que ahora no doy pie con bola. En realidad el problema hizo que iniciara este Hilo ya no es tal, ahora es otro, después de otros,... o sea, que te agradezco la respuesta, pero, me temo que mis problemas no terminan en la consulta SQL, sino que casi podría decirse que empiezan ahí... Tendré que leer sobre el tema y/o plantearme el proyecto que traigo entre manos de otra forma, desde un principio. Gracias igualmente. ;)

dec 19-09-2006 15:16:51

Hola,

Hoy he retomado el tema que se planteó al comienzo de este Hilo y me alegro de haberlo hecho, pues he visto que la consulta SQL que propone Emilio funciona bien y podría servirme para evitar enlaces "duplicados" en el listado de enlaces compartidos de cierta página Web de cuyo nombre no quiero acordarme. ;)

El caso es que estoy probando el "GROUP BY" y la cosa parece ir regularmente bien (tengo problemas con ciertas URLs, que parecen no tomarse como "iguales", aunque en realidad sí lo son... debe ser cuestión de las URLs, porque, se distingen de las que funcionan en que las que no tienen más caracteres y algunos caracteres como "&" y "?", por ejemplo.

Una cosa que quería preguntar... resulta que pruebo con una consulta SQL tal que así:

Código SQL [-]
SELECT DISTINCT login, url FROM usuarios, enlaces GROUP BY url

Y la cosa va más o menos como se espera (por el momento parece ir razonablemente bien con las pruebas que hemos hecho), pero, si la consulta se queda en esto:

Código SQL [-]
SELECT login, url FROM usuarios, enlaces GROUP BY url

O sea, si se quita el "DISTINCT" a la consulta SQL... se obtienen los mismos resultados... parece que la "magia" la hace el "GROUP BY" y, entonces, el "DISTINCT", ¿está demás? ¿sobraría? ¿cómo lo veis vosotros?

En todo caso muchas gracias a todos por la ayuda, y en especial a Emilio, que, habiéndome acercado a la solución, le respondí diciéndole que sí, pero, que no, en fin... cosas...

¡Gracias de nuevo a todos! :)

roman 19-09-2006 17:26:58

Cita:

Empezado por dec
parece que la "magia" la hace el "GROUP BY"

Y bastante magia ha de hacer. Habría que leer la documentación para ver qué hace MySql con ese GROUP BY pero no creo que sea estándar. No me quedaría claro qué sentido tiene agrupar por un campo y listar otro sin aplicarle alguna función de agrupación. Es decir, entiendo una consulta como

Código SQL [-]
select sum(costo), categoria from productos
group by categoria

donde se agrupan los registros por categoría y de cada grupo se calcula la suma de costos y es lo que se "imprime" junto a la categoría. Pero en una consulta como la que pones, se agrupa por URL y luego ¿qué se hace con cada grupo? ¿Cómo aparece el campo login en el conjunto de resultados? Vamos, si tengo la tabla

Código:

+---------+--------------------------+
| usuario | url                      |
+---------+--------------------------+
| pepe    |http://www.clubdelphi.com |
| juan    |http://www.clubdelphi.com |
| maria  |http://romansg.net        |
| roman  |http://romansg.net        |
| roman  |http://www.clubdelphi.com |
| maria  |http://www.clubdelphi.com |
+---------+--------------------------+

y agrupo por url, me quedan dos grupos, el de http://www.clubdelphi.com y el de http://romansg.net. ¿Cómo aparecenl listados? Quizá MySql agregue en automático el campo usuario al GROUP BY pero es lo que desconozco. En todo caso, quizá ahí haya que empezar, en la documentación.

// Saludos

dec 19-09-2006 17:44:53

Hola,

Pues sí, Román, supongo que tienes razón. Tengo por aquí La biblia de MySQL y procuro echar un vistazo y eso, y sobre GROUP BY hemos mirado, y sé que mi pregunta es de libro, es decir, puede localizarse en ellos, pero, no sé si será porque tengo la cabeza en dos o tres cosas... he querido plantear una solución al asunto y parece que funciona con la consulta que propuso Emilio.

Es cierto que me pones en un brete con lo que dices, porque se resalta que no he leído suficiente sobre MySQL ni me estoy preocupando de hacerlo por llevar a cabo otras cosas, ignorando que a lo mejor estas mismas cosas podrían llevarse a cabo de mejor modo, si antes leyera sobre MySQL... todo esto bien puede ser verdad.

Yo entiendo la siguiente consulta (seguramente mal, porque lo hago sin contrastar mi idea):

Código SQL [-]
SELECT DISTINCT login, url FROM usuarios, enlaces GROUP BY url

Como si dijéramos: "Selecciona el login y la url de la tabla usuarios y enlaces, pero, agrupados por su URL, es decir, siempre que estas últimas no se repitan".

Ahora bien, todavía y entendiendo mal la consulta anterior surge la pregunta de porqué esta otra consulta "parece funcionar", y entrecomillo porque a veces no se trata de que se produzcan errores: tal vez no se produzcan, pero, los resultados no sean del todo los perseguidos.

Digo que esta consulta ya sí que no la entiendo:

Código SQL [-]
SELECT login, url FROM usuarios, enlaces GROUP BY url

Porque falta el "DISTINCT",... y, sin embargo, tras ciertas pruebas, los resultados parecen los esperados: no se obtienen enlaces repetidos, que es lo que se persigue.

En fin. No voy a aburriros... el caso es que, efectivamente, estoy por dar marcha atrás y dejar las cosas como estaban: con la posibilidad que se listen enlaces repetidos, registros repetidos (en cierto modo, recuérdese que no son repetidos en todos sus campos), antes que utilizar una consulta SQl que, a qué negarlo, sin duda no termino de comprender...

roman 19-09-2006 17:50:47

Cita:

Empezado por dec
Es cierto que me pones en un brete con lo que dices, porque se resalta que no he leído suficiente sobre MySQL ni me estoy preocupando de hacerlo por llevar a cabo otras cosas, ignorando que a lo mejor estas mismas cosas podrían llevarse a cabo de mejor modo, si antes leyera sobre MySQL... todo esto bien puede ser verdad.

¿Brete? No escribí lo anterior como un regaño sino como una orientación. No era en el ánimo de evidenciar nada, simplemente señalar que a mi me da por que no es SQL estándar, y por tanto, para tener una respuesta acertada, es menester consultar en el manual en qué forma trata MySql al GROUP BY.

// Saludos


La franja horaria es GMT +2. Ahora son las 18:25:45.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi