Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

like con subquery

Estas en el tema de like con subquery en el foro de Mysql en Foros del Web. Buenas de nuevo y perdón por no recordar mis estudios de SQL, jeje Tengo un pequeño problema, con un LIKE y una subquery... necesito usar ...
  #1 (permalink)  
Antiguo 02/07/2012, 08:08
 
Fecha de Ingreso: abril-2012
Ubicación: 41°37′00″N, 00°37′00″E
Mensajes: 462
Antigüedad: 6 años, 8 meses
Puntos: 33
like con subquery

Buenas de nuevo y perdón por no recordar mis estudios de SQL, jeje

Tengo un pequeño problema, con un LIKE y una subquery... necesito usar un LIKE que dentro lleva una subquery; el problema está en que la subquery retorna varios valores...

Si hago el SQL con "in" en lugar de "like" me funciona, pero pierdo la ventaja de comparar parecidos...

Mi sql es algo así:

Código:
	select (campos)
	from t1, t2
	where t2.c1 = t1.c1 and
		  length(t2.c2) = 1 and
		  t2.c3 <> # and
		  t1.c2 like (select t1.c2
		               from t1, t2
					   where t2.c1 = t1.c1 and
					         length(t2.c2) = 1 and
					         t2.c3 = #) and
		 t2.c1 not in (select t2.c1
		                  from t2
		        		  where t2.c3 = #)
Los # serían los datos variables de la selección. La cosa está en que este select me devuelve una serie de datos que debería comparar por parecido (de ahí el LIKE), pero al recibir más de un registro me falla, por lo que si quiero que funcione tengo que usar un IN... lo que me quita la comparación...

Alguna sugerencia (si no recuerdo mal estas cosas se arreglaban con JOIN... pero hace tiempo que no refresco SQL...)??
  #2 (permalink)  
Antiguo 02/07/2012, 09:21
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.094
Antigüedad: 11 años, 11 meses
Puntos: 447
Respuesta: like con subquery

Hola DoHITB:

Es conveniente que nos digas primeramente qué es lo que quieres hacer... de entrada no le encuentro mucha lógica a tu consulta... es la primera vez que veo que alguien intenta hacer un like sobre una subconsulta, pero no logro descubrir qué es lo que pretendes. Te recomiendo que comiences por decirnos cuál es la estructura de tus tablas y que nos pongas algunos datos de ejemplo... a partir de estos datos dinos qué es lo que quiere obtener como salida. De esta manera es más fácil que podamos indicarte una solución alternativa.

Sin embargo, tengo que hacer algunas observaciones con respecto a la consulta por el tipo de elementos que estás utilizando.

Primero, no utilices comas para listar tablas, ni hagas las uniones en el WHERE... en lugar de esto utiliza JOIN's (INNER, LEFT o RIGTH según sea el caso)

Código:
En lugar de esto:
FROM Tabla1, Tabla2 WHERE Tabla1.Campo = Tabla2.Campo

Haz esto:
FROM Tabla1 INNER JOIN Tabla2 ON Tabla1.Campo = Tabla2.Campo
Segundo: las condiciones LIKE debes utilizarlas siempre para la búsqueda de patrones y para esto deberías utilizar los comodines (%, _, [])... Tal como estás poniendo tus consultas realmente no le sacas provecho al LIKE.

Tercero, las condiciones tipo IN son bastante ineficientes... trata en la medida de lo posible de evitarlas. En su defecto utiliza JOIN's.

Cuarto, el uso de subconsultas puede traer como consecuencia que tu consulta final sea también muy ineficiente, hay que tratar de evitarlas en la medida de lo posible. Además, en en este caso las subconsultas las estás haciendo sobre las mismas tablas que tienes en el FROM, cosa que no tiene mucho sentido. Sin embargo, como te comenté en un principio, sin datos de ejemplo de tus tablas resulta muy complicado tratar de hacerte una propuesta mejor que cumpla con los criterios que quieres incorporar a la consulta, así es que explícate un poco mejor y con gusto tratamos de ayudarte.

Saludos
Leo.
  #3 (permalink)  
Antiguo 02/07/2012, 09:43
 
Fecha de Ingreso: abril-2012
Ubicación: 41°37′00″N, 00°37′00″E
Mensajes: 462
Antigüedad: 6 años, 8 meses
Puntos: 33
Respuesta: like con subquery

Buenas Leo, gracias por contestar.

Te comento:

- Lo de unir tablas con JOIN: lo se, pero el tema de optimización de SQL (por ahora) es lo de menos. Sé que el IN es ineficiente y que las subquerys pueden causar mucho retardo en la consulta, pero esto es un tema que todavía no he abordado en mi proyecto (estoy pendiente de hacerlo)

- El like lo he dejado sin patrones porque he copiado el select que tenía con IN y lo he cambiado por LIKE, sin poner los patrones (en este caso iría con "%%")

Ahora, a ver si puedo explicar un poco mejor la finalidad de esta consulta (algo complicado cuando tienes política de privacidad en el proyecto... jeje)

Como puedes ver, ambas tablas tienen un campo común (un id numérico). La segunda tabla tiene un campo (id, numérico) que referencia una tercera tabla.
El campo "campo_busqueda" tiene una extensión de varchar, y puede estar repetido.

Código:
tabla1: t2_id, campo_busqueda
tabla2: t2_id, t3_id
tabla3: t3_id
Puede haber entradas en t1 sin referencia en t2, pero no puede ser viceversa (t2 es una tabla intermedia), lo mismo entre t3 y t2.

Entonces, lo que busco son registros de la tabla1 los cuales estén referenciados en tabla2 pero NO referencie a cierto registro de tabla3, y cuyo campo_busqueda sea similar a algún registro de tabla1 que esté referenciado en tabla1 Y exista cierto registro en la tabla3

Cuando digo "Cierto registro" me refiero a datos que variarán dependiendo del contexto (los # del mensaje anterior).

El tema del "length..." olvídalo, es otro filtro de selección que no viene al caso.

Espero poder haber sido más claro ahora...

De nuevo gracias por tu tiempo
  #4 (permalink)  
Antiguo 02/07/2012, 09:55
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.094
Antigüedad: 11 años, 11 meses
Puntos: 447
Respuesta: like con subquery

Hola de nuevo DoHITB:

Quedé en las mismas... Tal vez a ti te parezca de lo más clara tu explicación, pero la verdad es que yo no te entendí nada... En mi Post pasado te pedía algunos DATOS de ejemplo, ya que de esta manera lo que pretendes lo puedes explicar mejor... y no te estoy pidiendo que me entregues toda la BD de la empresa, ni siquiera que pongas datos reales... Si checas cualquiera de los mensajes que he contestado, cuando quiero poner algún ejemplo pongo datos como estos:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM tabla;
  2. +------+-------------+
  3. | id   | descripcion |
  4. +------+-------------+
  5. |    1 | UNO         |
  6. |    2 | DOS         |
  7. |    3 | TRES        |
  8. +------+-------------+
  9. 3 rows in set (0.00 sec)

Te aseguro que estos datos NO VIOLAN NINGUNA POLÍTICA DE CONFIDENCIALIDAD. esto es lo que quiero que pongas... Pon tres o cuatro registros en cada una de tus tres tablas, con datos inventados, no hay problema... pero creo que te estás complicando la existencia.

Saludos
Leo.
  #5 (permalink)  
Antiguo 02/07/2012, 13:51
 
Fecha de Ingreso: abril-2012
Ubicación: 41°37′00″N, 00°37′00″E
Mensajes: 462
Antigüedad: 6 años, 8 meses
Puntos: 33
Respuesta: like con subquery

Bueas de nuevo Leo,
Ya se que me complico la existencia... hace poco que estoy en el mundo laboral (y menos aún con acuerdos de este tipo) y además me resulta muy difícil usar un ejemplo que refleje lo que quiero hacer en esta query...
He estado tratando de buscar un ejemplo práctico, y espero que aclare bastante las cosas:

Tenemos tres tablas: COCHE, PERSONA, PROPIEDAD, ok?


Código:
COCHE:                                    PERSONA:                              PROPIEDAD:
(id/nombre)
1 / Toyota Auris
2 / Ford Fiesta
3 / Nuevo Ford Fiesta

PERSONA:
(id/nombre)
1 / DöH
2 / Leo

PROPIEDAD:
(id/coche/persona)

1 / 1 / 1
2 / 1 / 2
3 / 2 / 1
4 / 2 / 2
5 / 3 / 1
Bien, lo que quiero hacer con el SQL es lo siguiente (explicado con palabras): "Como DöH y Leo tienen un Ford Fiesta, y DöH tiene un Nuevo Ford fiesta, y el nombre de este coche es parecido al coche que tienen ámbos, mostramos a Leo el "Nuevo Ford Fiesta"...", es decir, como ambos tendríamos un coche en común y yo tengo uno que tú no tienes pero es parecido, quizás tu deberías saberlo.

Espero que esto sea bastante más aclaratorio... siguiendo con este ejemplo, mi sql quedarías así:

Código:
usando el # = 2

select c.nombre
	from coche c, propiedad p
	where p.coche = c.id and
		  p.persona <> 2 and
		  c.nombre like (concat('%', select c.nombre
		               from coche c, propiedad p
					   where p.coche = c.id and
					         p.persona = 2) and
		 p.coche not in (select coche
		                  from propiedad
		        		  where persona = 2)
Espero que ahora sí puedas ver claro lo que hace la query y puedas echarme una mano

Saludos
  #6 (permalink)  
Antiguo 02/07/2012, 15:23
Colaborador
 
Fecha de Ingreso: enero-2007
Ubicación: México
Mensajes: 2.094
Antigüedad: 11 años, 11 meses
Puntos: 447
Respuesta: like con subquery

Hola de nuevo.

Por como describes el problema, creo que quiere mostrar una especie de lista de cosas que cierto grupo de personas tienen en común a partir de los objetos tienes como propiedad cierto??? veamos si esto es más o menos lo que buscas, supongamos que tenemos estos datos:

Código MySQL:
Ver original
  1. mysql> SELECT * FROM coche;
  2. +------+-------------------+
  3. | id   | nombre            |
  4. +------+-------------------+
  5. |    1 | Toyota Auris      |
  6. |    2 | Ford Fiesta       |
  7. |    3 | Nuevo Ford Fiesta |
  8. |    4 | Toyota            |
  9. +------+-------------------+
  10. 4 rows in set (0.08 sec)
  11.  
  12. mysql> SELECT * FROM persona;
  13. +------+--------+
  14. | id   | nombre |
  15. +------+--------+
  16. |    1 | DöH    |
  17. |    2 | Leo    |
  18. |    3 | Otro   |
  19. +------+--------+
  20. 3 rows in set (0.00 sec)
  21.  
  22. mysql> SELECT * FROM propiedad;
  23. +------+-------+---------+
  24. | id   | coche | persona |
  25. +------+-------+---------+
  26. |    1 |     1 |       1 |
  27. |    2 |     1 |       2 |
  28. |    3 |     2 |       1 |
  29. |    4 |     2 |       2 |
  30. |    5 |     3 |       1 |
  31. |    6 |     4 |       3 |
  32. +------+-------+---------+
  33. 6 rows in set (0.00 sec)

Si el parámetro de búsqueda fuera la persona 2 (Leo) podrías hacer algo como esto:

Código MySQL:
Ver original
  1. mysql> SELECT
  2.     ->   persona.id, persona.nombre,
  3.     ->   coche.id, coche.nombre
  4.     -> FROM coche
  5.     -> INNER JOIN
  6.     ->   ( SELECT coche.nombre coche
  7.     ->     FROM propiedad
  8.     ->     INNER JOIN coche ON propiedad.coche = coche.id
  9.     ->     WHERE propiedad.persona = 2
  10.     ->   ) A ON ( coche.nombre LIKE CONCAT('%', A.coche, '%') OR
  11.     ->            A.coche LIKE CONCAT('%', coche.nombre, '%')
  12.     ->          )
  13.     ->          AND coche.nombre != A.coche
  14.     -> INNER JOIN propiedad ON propiedad.coche = coche.id
  15.     -> INNER JOIN persona ON propiedad.persona = persona.id;
  16. +------+--------+------+-------------------+
  17. | id   | nombre | id   | nombre            |
  18. +------+--------+------+-------------------+
  19. |    1 | DöH    |    3 | Nuevo Ford Fiesta |
  20. |    3 | Otro   |    4 | Toyota            |
  21. +------+--------+------+-------------------+
  22. 2 rows in set (0.00 sec)

El usuari 1 (DöH) aparece en el listado porque tiene tiene un Nuevo Ford Fiesta que su descripción es similar a Ford Fiesta... el usuario 3 (otro) aparece pues tiene un Toyota, que su descripción es similar a Toyota Auris y

Falta un pequeño detalle con respecto a lo lo que planteas en tu problema original, y es el hecho de que en realidad el usuario 3 (Otro) NO COMPARTE NINGUNA COCHE EN COMUN con el usuario 2... faltaría agregar una condición WHERE donde especifiques que EXISTA esta relación (y si no te queda claro te digo que necesitas hacer un EXISTS...), me gustaría que lo intentaras sacar por tu cuenta...

Observa que la condición LIKE la hago de de dos formas:

Código:
( coche.nombre LIKE CONCAT('%', A.coche, '%') OR
  A.coche LIKE CONCAT('%', coche.nombre, '%')
)
Esto es necesario porque:

Código MySQL:
Ver original
  1. mysql> select 'Ford Fiesta' LIKE '%Nuevo Ford Fiesta%';
  2. +------------------------------------------+
  3. | 'Ford Fiesta' LIKE '%Nuevo Ford Fiesta%' |
  4. +------------------------------------------+
  5. |                                        0 |
  6. +------------------------------------------+
  7. 1 row in set (0.00 sec)
  8.  
  9. mysql> SELECT 'Nuevo Ford Fiesta' LIKE '%Ford Fiesta%';
  10. +------------------------------------------+
  11. | 'Nuevo Ford Fiesta' LIKE '%Ford Fiesta%' |
  12. +------------------------------------------+
  13. |                                        1 |
  14. +------------------------------------------+
  15. 1 row in set (0.00 sec)

Dale un vistazo para ver si te sirve...

Saludos

Etiquetas: join, select, sql, subquery, campos
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 01:19.