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

Select para 3 tablas.

Estas en el tema de Select para 3 tablas. en el foro de Mysql en Foros del Web. Buenos dias, tengo este select y no funciona. Código: SELECT usuarios.nombre, usuarios.apellidos, usuarios.nu_usuario, usuarios.telefono, dir_usuarios.poblacion, ap_usuarios.aparato, ap_usuarios.marca, ap_usuarios.modelo, ap_usuarios.num_serie, ap_usuarios.num_producto, ap_usuarios.fecha_compra FROM dir_usuarios, usuarios, ap_usuarios ...

  #1 (permalink)  
Antiguo 13/09/2012, 04:16
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Select para 3 tablas.

Buenos dias, tengo este select y no funciona.

Código:
SELECT usuarios.nombre, usuarios.apellidos, usuarios.nu_usuario, usuarios.telefono, dir_usuarios.poblacion, ap_usuarios.aparato, ap_usuarios.marca, ap_usuarios.modelo, ap_usuarios.num_serie, ap_usuarios.num_producto, ap_usuarios.fecha_compra
FROM dir_usuarios, usuarios, ap_usuarios
WHERE dir_usuarios.usuario = usuarios.nu_usuario=ap_usuarios.num_usuario
AND CONCAT( nombre, ' ', apellidos ) LIKE '%pulido%'
AND telefono LIKE '%600000000%'
AND poblacion LIKE '%JAEN%'
Un saludo.
  #2 (permalink)  
Antiguo 13/09/2012, 04:28
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

¿No funciona qué?
¿No devuelve datos?
¿Devuelve un error?
¿Devuelve datos que no son los buscados?

Por lo pronto, debería estar escrita así (creí que era obvio que no puedes escribir A = B = C ):
Código MySQL:
Ver original
  1.     usuarios.nombre,
  2.     usuarios.apellidos,
  3.     usuarios.nu_usuario,
  4.     usuarios.telefono,
  5.     dir_usuarios.poblacion,
  6.     ap_usuarios.aparato,
  7.     ap_usuarios.marca,
  8.     ap_usuarios.modelo,
  9.     ap_usuarios.num_serie,
  10.     ap_usuarios.num_producto,
  11.     ap_usuarios.fecha_compra
  12.     dir_usuarios, usuarios, ap_usuarios
  13.     dir_usuarios.usuario = usuarios.nu_usuario
  14.     AND usuarios.nu_usuario=ap_usuarios.num_usuario
  15.     AND CONCAT( nombre, ' ', apellidos ) LIKE '%pulido%'
  16.     AND telefono LIKE '%600000000%'
  17.     AND poblacion LIKE '%JAEN%'

pero sería mejor y más claro así:
Código MySQL:
Ver original
  1.     U.nombre,
  2.     U.apellidos,
  3.     U.nu_usuario,
  4.     U.telefono,
  5.     D.poblacion,
  6.     A.aparato,
  7.     A.marca,
  8.     A.modelo,
  9.     A.num_serie,
  10.     A.num_producto,
  11.     A.fecha_compra
  12.     dir_usuarios D INNER JOIN usuarios U ON D.usuario = U.nu_usuario
  13.     INNER JOIN ap_usuarios A ON U.nu_usuario = A.num_usuario
  14.     CONCAT( nombre, ' ', apellidos ) LIKE '%pulido%'
  15.     AND telefono LIKE '%600000000%'
  16.     AND poblacion LIKE '%JAEN%';
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 13/09/2012, 16:30
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Compañero me he complicado mas con una cuarta tabla llamada avisos, me duplica resultados y tarda mucho lo que busca :
Código PHP:
SELECT 
    U
.nombre
    
U.apellidos
    
U.nu_usuario
    
U.telefono
    
D.poblacion
    
A.aparato
    
A.marca
    
A.modelo
    
A.num_serie
    
A.num_producto
    
A.fecha_compra,
    
B.num_aviso,
    
B.num_usuario,
    
D.calle,
    
B.fecha_recepcion,
    
B.fecha_emision,
    
B.sintoma
FROM 
    dir_usuarios D INNER JOIN usuarios U ON D
.usuario U.nu_usuario
    INNER JOIN ap_usuarios A ON U
.nu_usuario A.num_usuario
    INNER JOIN avisos B ON U
.nu_usuario B.num_usuario
WHERE 
    CONCAT
nombre' 'apellidos LIKE '%%'
    
AND telefono LIKE '%%'
    
AND poblacion LIKE '%%' 

Última edición por satjaen; 14/09/2012 a las 16:04
  #4 (permalink)  
Antiguo 17/09/2012, 00:52
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Por favor, puede contestarme alguien?
  #5 (permalink)  
Antiguo 17/09/2012, 04:21
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

Cita:
Compañero me he complicado mas con una cuarta tabla llamada avisos, me duplica resultados y tarda mucho lo que busca :
Un INNER JOIN no puede duplicar resultados, a menos que los datos básicos estén duplicados.
Si el campo usuario.nu_ usuario es PK, entonces no existe duplicidad de datos. Pero si la tabla dir_usuario representa el domicilio, y un usuario puede declarar más de un domicilio, parte de los datos se repetirá entre registros. Eso no solo es evidente, sino que es correcto.
Por otro lado, si un usuario sólo debe tener una dirección, entonces no tiene sentido ponerla en una tabla separada.
Respecto a las duplicidades, para hablar de tales habría que verificar si el contenido completo de los registros relacionados se duplica. Que se repita una selección de datos (parcial), solo muestra que existe una relación 1:N entre las tablas, pero no implica que haya repeticiones exactamente, sino mas bien una incorrecta normalización de las tablas, porque si existen datos que se repiten entre registros relacionados con otra tabla, entonces o hay un error de ingreso de datos, o la tabla no está correctamente normalizada (subgrupos de datos repetitivos violan la 1FN).
Para darte una respuesta más concreta deberíamos ver datos resultantes de la consulta.

Finalmente, esto:
Código MySQL:
Ver original
  1. CONCAT( nombre, ' ', apellidos ) LIKE '%%'
  2.     AND telefono LIKE '%%'
  3.     AND poblacion LIKE '%%'
Yo no le encuentro ningún sentido...
¿Podrías explicar qué se supone que estás buscando en ese WHERE?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #6 (permalink)  
Antiguo 17/09/2012, 05:25
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Entendido en cuanto a la duplicidad de datos, pero por ahora solo quiero saber si esta correctamente el select.
En cuanto a:

Código PHP:
CONCATnombre' 'apellidos LIKE '%%'
    
AND telefono LIKE '%%'
    
AND poblacion LIKE '%%' 
Es para filtrar datos que tengo en formulario con campos llamados nombre,telefono, etc....

Tengo que poner como PK a nsuario (en las demas tablas se llama de otra forma) si solo lo tengo en la tabla usuarios ya que puede haber varios registros con un mismo nº de usuario?


Muchas gracias por todo.
  #7 (permalink)  
Antiguo 17/09/2012, 06:38
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

Mi duda respecto a ese WHERE es que en realidad no filtra nada, por lo que parece pedir es todo aquello que comience con cualquier cosa, y termine con cualquier cosa... Es decir, todo.
Entonces no se ve para qué lo pones, porque daría lo mismo que sin ello.

En cuanto al resto de la sintaxis, es correcta, pero como estás usando INNER JOIN y no LEFT JOIN en algunas de las relaciones, sólo devolverá datos si hay coincidencias en todas las tablas al mismo tiempo.

Es decir, sólo saldrán aquellos usuarios que tengan dirección declarada que tengan aparatos declarados, y posean avisos.
El problema de duplicidad que puedes encontrar es que un INNER JOIN de esas características, donde todas las tablas se relacionan con una única tabla, pero no tienen dependencias entre ellas, tienden a generar un producto cartesiano. Es un caso especial del producto cartesiano.
Me explico:
Las tablas de usuario y dirección te devuelven un registro por cada dirección del usuario. Pero como puede haber más de una, te puede devolver más de una vez a algunos usuarios.
Esa tabla derivada generada por el primer INNER JOIN se cruzará con la de aparatos, una vez por cada aparato, en cada una de las apariciones del usuario en la derivada, pero ésta instancia del usuario.
A su vez, cuando se cruce con los avisos, lo hará por cada usuario que a parezca en la segunda derivada... por cada aviso de ese usuario.
En definitiva se puede formar un producto cartesiano así:
100 usuarios con 2 direcciones cada uno: 200 registros (2 por usuario)
200 usuarios duplicados) por cinco aparatos cada usuario: 1.000 registros.
1.000 registros por 3 avisos por usuario: 3.000 registros.
Es decir que:
- Cada dirección de cada usuario aparecerá 150 veces
- Cada usuario aparecerá 300 veces.
- Cada aparato aparecerá 1500 veces.
- Cada aviso aparecerá 900 veces.

El tema es que no puedes relacionar toda esas tablas en forma de estrella, sino que tienen que tener una relación lineal. De lo contrario deberás hacer consultas separadas.
Es decir:
- Un usuario
tiene 1:N direcciones (Relación usuario <- direccion).
- En cada direccion publica 1:N avisos (relación usuario+direccion <-> avisos).
- Cada aviso es sobre un aparato (relación usuario+direccion+aviso <- aparato).
Entonces es una dependencia bastante diferente a la que planteas.

¿Se entiende el problema?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #8 (permalink)  
Antiguo 17/09/2012, 06:48
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Ok, muchas gracias y como quedaría con LEFT INNER JOIN y ademas añadiendo otra tabla llamada facturas?
  #9 (permalink)  
Antiguo 17/09/2012, 07:22
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

Mas o menos:
Código MySQL:
Ver original
  1.     U.nombre,
  2.     U.apellidos,
  3.     U.nu_usuario,
  4.     U.telefono,
  5.     D.poblacion,
  6.     A.aparato,
  7.     A.marca,
  8.     A.modelo,
  9.     A.num_serie,
  10.     A.num_producto,
  11.     A.fecha_compra,
  12.     B.num_aviso,
  13.     B.num_usuario,
  14.     D.calle,
  15.     B.fecha_recepcion,
  16.     B.fecha_emision,
  17.     B.sintoma
  18.  
  19.     usuarios U INNER JOIN dir_usuarios D ON U.nu_usuario
  20.  = D.usuario  
  21.  
  22.     LEFT JOIN ap_usuarios A ON D.usuario = A.num_usuario
  23.  AND D.id_direccion = A.id_direccion
  24.     LEFT JOIN avisos B ON A.num_usuario = B.nu_usuario AND
  25. A.id_aparato = B.id_aparato AND  A.id_direccion = B.id_direccion;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #10 (permalink)  
Antiguo 17/09/2012, 08:29
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

No funciona, te digo que en las cuatro tablas tengo un campo igual que es:

USUARIO ---> NU_USUARIO

AP_USUARIOS-----> NU_USUARIO

AVISOS--------> NUM_USUARIO

DIR_USUARIOS-----> USUARIO


-GRACIAS.
  #11 (permalink)  
Antiguo 17/09/2012, 08:44
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

Vuelve a leer lo que te digo en el penúltimo post mío. Creo que no lo estás entendiendo bien.
El ejemplo que te doy de los LEFT JOIN implica que las tablas que tienes están incompletas. Las relaciones que faltan se tienen que poner para evitar el producto cartesiano. Sin esas relaciones, la unicidad de los registros devueltos por la consulta se pierde, y tienes datos basura en cantidades industriales.
La lógica que se te está escapando es que:
- Un usuario debe tener una o más direcciones.
- La misma dirección puede corresponder a diferentes usuarios (no es identificatoria)
- Un usuario puede publicar uno o más avisos, pero cada aviso sólo puede corresponder a una única dirección y un único usuario.
- Cada aviso debe corresponder a un único aparato, pero cada aparato puede aparecer en diferentes avisos.

El hecho de que la FK del usuario pueda ser puesta en cada tabla, por cuestiones de optimizacion de consultas, no implica que en la consulta los JOIN apunten todos a la misma tabla, precisamente por la posibilidad que te expliqué de generar el producto cartesiano.

¿Se entiende la lógica del asunto?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #12 (permalink)  
Antiguo 17/09/2012, 08:53
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Hola otra vez gnzsoloyo, he probado con esto y no me funciona:


Código PHP:
Error

consulta SQL
Documentación

SELECT U
.nombreU.apellidosU.nu_usuarioU.telefonoD.poblacionA.aparatoA.marcaA.modeloA.num_serieA.num_productoA.fecha_compraB.num_avisoB.num_usuarioD.calleB.fecha_recepcionB.fecha_emisionB.sintoma
FROM usuarios U
INNER JOIN dir_usuarios D ON U
.nu_usuario D.usuario
LEFT JOIN ap_usuarios A ON D
.usuario A.nu_usuario
AND D.USUARIO A.USUARIO
LEFT JOIN avisos B ON A
.nu_usuario B.num_usuario
AND A.nu_usuario B.nu_usuario
AND A.usuario B.usuario
LIMIT 0 
30

MySQL ha dicho
Documentación
#1054 - Unknown column 'A.nu_usuario' in 'on clause' 



y sin embargo con tres tablas me funciona a la perfección:


Código PHP:
SELECT 
    U
.nombre
    
U.apellidos
    
U.nu_usuario
    
U.telefono
    
D.poblacion
    
A.aparato
    
A.marca
    
A.modelo
    
A.num_serie
    
A.num_producto
    
A.fecha_compra
FROM 
    dir_usuarios D INNER JOIN usuarios U ON D
.usuario U.nu_usuario
    INNER JOIN ap_usuarios A ON U
.nu_usuario A.num_usuario
WHERE 
    CONCAT
nombre' 'apellidos LIKE '%$vnm%'
    
AND telefono LIKE '%$vte%'
    
AND poblacion LIKE '%$vpo%' 
  #13 (permalink)  
Antiguo 17/09/2012, 09:02
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

Cita:
#1054 - Unknown column 'A.nu _usuario' in 'on clause'
¿Y no te resulta evidente de que te está diciendo que la columna "nu _usuario" no existe en la tabla "ap_usuarios"?
Eso es un error típico del Copy+Paste.
Tienes que verificar siempre antes de ejecutar que esté todo bien. ten en cuenta que esas tablas son tuyas, nosotros no las tenemos y por tanto podemos cometer algún error al copiar las sentencias.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 17/09/2012 a las 09:53
  #14 (permalink)  
Antiguo 17/09/2012, 09:38
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Y entonces como filtro para buscar por telefono,nombre etc...?

Que te parece esta consulta?

Código PHP:
SELECT
U
.nombre
U.apellidos
U.nu_usuario
U.telefono
D.poblacion
A.aparato
A.marca
A.modelo
A.num_serie
A.num_producto
A.fecha_compra
B.num_aviso
B.num_usuario
D.calle
B.fecha_recepcion
B.fecha_emisionB.sintoma
FROM usuarios U
INNER JOIN dir_usuarios D ON U
.nu_usuario D.usuario
LEFT JOIN ap_usuarios A ON D
.usuario A.num_usuario
AND D.USUARIO A.num_USUARIO
LEFT JOIN avisos B ON A
.num_usuario B.num_usuario
AND U.nu_usuario D.usuario 
  #15 (permalink)  
Antiguo 17/09/2012, 09:55
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

Estás andando en círculos.
¿No quieres o no puedes modificar las relaciones de esas tablas, para así poder evitar el producto cartesiano?

¿Hay alguna cosa de lo que te digo que no se entienda bien?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #16 (permalink)  
Antiguo 17/09/2012, 10:56
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

No puedo modificar las tablas!
  #17 (permalink)  
Antiguo 17/09/2012, 11:08
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

OK. Entonces en ese caso creo que no vas a poder hacer la consulta optimizada...
Hay tres soluciones:
1) Hacer un GROUP BY final de modo que elimine las duplicidades de datos que se acumulan en los INNER JOIN, horrible idea, porque tanto el ORDER BY como el GROUPO BY son asesinos de performance.

2) Manejarlo por medio de un stored procedure, de modo que genere una tabla de tipo temporary que acumule los datos de tres consultas secuenciales. La idea es interesante, pero requiere cierta práctica y conocimiento de los SP.

3) Hacer las consultas separadamente e integrar los resultados de forma programática (en la aplicación).
A nivel de performance, es posible que la tercera opción sea bastante buena idea... pese a que no me gusta hacerlo de esa forma.

Lo que seguro no vas a poder hacerlo es en una única consulta, al menos no del modo que la planteas.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #18 (permalink)  
Antiguo 17/09/2012, 12:38
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Esta consulta me tarda en myadmin aprox 8 minutos.Pero funciona bien, se puede mejorar?

Código PHP:
SELECT 
U
.nombre
U.apellidos
U.nu_usuario
U.telefono
A.aparato
A.marca
A.modelo
A.num_serie
A.num_producto
A.fecha_compra
D.poblacion
D.calle
E.num_aviso
E.num_usuario
E.aparato
E.fecha_recepcion
E.fecha_emision
E.sintoma
FROM dir_usuarios D
usuarios Uap_usuarios Aavisos E
WHERE 
U
.NU_USUARIO A.NUM_USUARIO
AND D.USUARIO U.NU_USUARIO
AND U.NU_USUARIO E.NUM_USUARIO
AND CONCATnombre' 'apellidos LIKE '%TOMAS%'
AND telefono LIKE '%600000000%'
AND poblacion LIKE '%JAEN%' 
Muchas gracias por vuestro tiempo.
  #19 (permalink)  
Antiguo 17/09/2012, 12:45
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

Código MySQL:
Ver original
  1. FROM dir_usuarios D, usuarios U, ap_usuarios A, avisos E
  2. U.NU_USUARIO = A.NUM_USUARIO
  3. AND D.USUARIO = U.NU_USUARIO
  4. AND U.NU_USUARIO = E.NUM_USUARIO
y
Código MySQL:
Ver original
  1.     dir_usuarios D INNER JOIN usuarios U ON D.usuario = U.nu_usuario
  2.     INNER JOIN ap_usuarios A ON U.nu_usuario = A.num_usuario
  3.     INNER JOIN avisos B ON U.nu_usuario = B.num_usuario
Para el parser de MySQL son equivalentes
Eliminar los INNER JOIN no va a mejorar la performance, e incluso puede empeorarla (por ciertas razones de los algoritmos internos).
En tanto se produzca el producto cartesiano que te describí (del que no me has hecho ningún comentario), no vas a obtener una performance mejor.
Puedes obtener algunas mejoras relativas usando indices FULLTEXT con los campos que pones en el WHERE, y usando MATCH(...) AGAINST(...), pero eso es todo. Mientras siga existiendo el riesgo de generar esos productos cartesianos... no hay mucho más que hacer.

Mi consejo es que trates de ver si puedes modificar las tablas para resolverlo.
Hay ocasiones en que no se puede resolver un mal diseño, si no es aplicando el bisturí.


Pero, bueno, es tu decisión (o la de quien sea).
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 17/09/2012 a las 12:58
  #20 (permalink)  
Antiguo 18/09/2012, 10:10
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Hola, he solucionado el tema con dos tablas (USUARIOS Y DIR_USUARIOS) y un filtro por nº de telefono y quisiera saber si hay alguna forma de filtrarlos tambien por población o/y nombre y si pudieramos ya de paso hacer la consulta con las tablas AP_USUARIOS,AVISOS Y FACTURAS,ya que estan relecionadas las cuatro tablas entre ellas:


U A B D F
TABLA ------USUARIOS AP_APARATOS AVISOS DIR_USUARIOS FACTURAS
RELACION-- nsuario num_usuario num_usuario usuario num_usuario




ajax.php


Código PHP:
<?php 
include("conexion.php");
if (
$_GET["action"] == "listar")
{
    
// valores recibidos por POST
    
$vnm   $_POST['nombre_apellidos'];
    
$vpo $_POST['poblacion'];
    
$vte $_POST['telefono'];
    
$vdel  = ($_POST['del'] != '' ) ? explode("/",$_POST['del']) : ''
    
$val   = ($_POST['al']  != '' ) ? explode("/",$_POST['al']) : '';
    
    
$sql "SELECT
    U.nombre, 
               U.apellidos, 
               U.nu_usuario, 
               U.telefono,
    D.poblacion
    FROM USUARIOS U, DIR_USUARIOS D
    WHERE 
    U.NU_USUARIO=D.USUARIO
    AND U.telefono like '%$vte%'"
;     
                                
    
// Ordenar por
    
$vorder $_POST['orderby'];
    
    if(
$vorder != ''){
        
$sql .= " ORDER BY ".$vorder;
    }
    
    
$query mysql_query($sql);
    
$datos = array();
    
    while(
$row mysql_fetch_array($query))
    {
        
$datos[] = array(
            
'nu_usuario'          => $row['nu_usuario'],
            
'telefono'          => $row['telefono'],
            
'nombre'      => $row['nombre'],
            
'apellidos'       => $row['apellidos'],
            
'poblacion'        => $row['poblacion'],
            
'aparato'          => $row['aparato'],
            
'marca'          => $row['marca'],
            
'modelo'      => $row['modelo'],
            
'num_serie'       => $row['num_serie'],
            
'num_producto'        => $row['num_producto'],
            
'fecha_compra'        => $row['fecha_compra'],
            
'num_aviso'          => $row['num_aviso'],
            
'num_usuario'          => $row['num_usuario'],
            
'aparato'      => $row['aparato'],
            
'calle'       => $row['calle'],
            
'fecha_recepcion'        => $row['fecha_recepcion'],
            
'fecha_emision'        => $row['fecha_emision'],
            
'sintoma'        => $row['sintoma']
        );
    }
    
// convertimos el array de datos a formato json
    
echo json_encode($datos);
}

?>

GRACIAS
  #21 (permalink)  
Antiguo 20/09/2012, 02:01
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Por favor, puede contestar alguien?
  #22 (permalink)  
Antiguo 20/09/2012, 03:39
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Select para 3 tablas.

Yo ya te di mi opinión, pero no me has hecho ninguna observación sobre el asunto.

Saludos
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #23 (permalink)  
Antiguo 20/09/2012, 04:50
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Select para 3 tablas.

algunas preguntas:
¿qué motor de tablas usas, InnoDB o MyIsam?
Si usas MyIsam, ¿tienes indexados los FK, es decir, esos, nsuario, num_usuario, y usuario, excepto el usuario de la tabla usuario, pues imagino que ese lo tendrás como PK.

USUARIO ---> NU_USUARIO

AP_USUARIOS-----> NU_USUARIO

AVISOS--------> NUM_USUARIO

DIR_USUARIOS-----> USUARIO

Si los indexas, ganarás en velocidad.

El otro problema que veo es que quieres tener la posibilidad de buscar por población, teléfono y nombre. El campo donde va el nombre, el teléfono y población también deberían ir indexados, pero es que además deberías configurar la consulta dependiendo de lo que se pida, sea nombre solamente, (lo que podría arrastrar varias direcciones), teléfono, y población. La población es de direcciones, mientras que teléfono es de usuario. Si solo pasas un parámetro para teléfono, deberías buscar sólo en la tabla usuario; Si la población forma parte de la consulta, tendrás que relacionar con dir_usuarios, pero ojo, un usuario podría tener dos direcciones distintas en la misma localidad (si el detalle de cada dirección no importa, no hay problema, pues te traes el identificador del usuario, pero si quieres poner todas las direcciones, el group by por nsuario, no te dejará. Yo, en tu caso, armaría consultas distintas de acuerdo con los valores pasados por POST. Danos los datos de las consultas según 1, 2 o 3 parámetros y qué querrías mostrar. Nosotros te orientaremos sobre esas posibles consultas y en el foro PHP lo harán sobre los demás aspectos. Dinos también si querrás mostrar otros datos, porque una vez sacado el num podríamos hacer subconsultas sobre los demás datos que quizás mejoraran esos LEFT JOIN de todas las tablas con todos los campos. Primero nos traemos los 2, 5 o 10 datos de la consulta y con subconsulta le añadimos lo demás.
  #24 (permalink)  
Antiguo 20/09/2012, 06:03
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Jurena, muchas gracias por responder.
He podido modificar las tablas(que antes no podia).

USUARIOS ---> NUM_USUARIO- FK

AP_USUARIOS-----> NUM_USUARIO------ FK-------->NUM_APARATO

AVISOS--------> NUM_USUARIO---- FK---->INDICE

DIR_USUARIOS-----> NUM_USUARIO----- FK---->INDICE

Que te parece, podriamos ya hacer la consulta del principio?

Código PHP:
SELECT 
U
.nombre
U.apellidos
U.nu_usuario
U.telefono
A.aparato
A.marca
A.modelo
A.num_serie
A.num_producto
A.fecha_compra
D.poblacion
D.calle
E.num_aviso
E.num_usuario
E.aparato
E.fecha_recepcion
E.fecha_emision
E.sintoma
FROM dir_usuarios D
usuarios Uap_usuarios Aavisos E
WHERE 
U
.NU_USUARIO A.NUM_USUARIO
AND D.USUARIO U.NU_USUARIO
AND U.NU_USUARIO E.NUM_USUARIO
AND CONCATnombre' 'apellidos LIKE '%TOMAS%'
AND telefono LIKE '%600000000%'
AND poblacion LIKE '%JAEN%' 




Los motores:

Motores de almacenamiento
Motor de almacenamiento Descripción
MyISAM Default engine as of MySQL 3.23 with great performance
CSV CSV storage engine
MRG_MYISAM Collection of identical MyISAM tables
BLACKHOLE /dev/null storage engine (anything you write to it disappears)
FEDERATED Federated MySQL storage engine
InnoDB Supports transactions, row-level locking, and foreign keys
ARCHIVE Archive storage engine
MEMORY Hash based, stored in memory, useful for temporary tables





Gracias.

Última edición por satjaen; 20/09/2012 a las 07:59
  #25 (permalink)  
Antiguo 20/09/2012, 08:22
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Select para 3 tablas.

Otra pregunta: ¿seguro que quieres buscar por esos 3 valores con AND, es decir, siempre tienen que estar los tres campos rellenos y los tres filtros tienen que obtener resultado, es decir, que entre nombre y apellidos aparezca TOMAS, que el teléfono contenga 600000000 y que la ciudad sea JAEN, y además que ese o esos TOMAS de JAEN, con 600000000 en el teléfono tenga avisos y ap_usuarios. Si buscas así, un TOMÁS que o no sea de JAEN, o no tenga un teléfono 600000000 o simplemente que no tenga avisos o ap_usuarios con su num_usuario, no saldrá, es más, aunque tenga todo excepto lo último, ap_usuarios, no saldrá con esos INNER JOIN. Si es eso lo que quieres, dínoslo y buscaremos el mejor modo de hacerlo.
Veo que el MySQL es 3.23, con lo que lo de las subconsultas queda descartado. Habrá que solucionar con más de una consulta, pero primero dinos si lo que quieres es que en cuanto aparezca TOMAS ya salgan resultados, aunque no sea de JAEN, etc.
  #26 (permalink)  
Antiguo 20/09/2012, 10:19
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Jurena, no lo de los tres valores ha sido un ejemplo.Lo que tengo es un formulario con muchos campos como nombre,telefono,poblacion,aparato,marca,modelo etc, donde lo que quiero es que al poner cualquiera de ellos, lo reconozca el ajax.php descrito mas arriba.
Gracias.
  #27 (permalink)  
Antiguo 20/09/2012, 10:55
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Select para 3 tablas.

No veo ningún ajax.php
No sé si te refieres a ajax. En este foro no podríamos ayudarte sobre eso. Pero si lo que quieres decir es que tienes un formulario con nombre,telefono,poblacion,aparato,marca,modelo
y que al escribir en un campo cualquiera te busque; si fuera solo al escribir en uno, prepararíamos las consultas dependiendo del campo, pero parece que si escribes en dos o en más, la consulta se haría lógicamente con AND, porque quieres que se cumplan ambas a la vez (¿no?), y si son más lo mismo, pero observa que población requiere un inner join con usuario; y que aparato,marca y modelo requiere búsquedas sobre sus tablas e inner join con usuario; pero si quieres todo a la vez, tienes dos opciones, o buscas con LEFT JOIN y evitas los duplicados mediante GROUP BY, o lanzas varias consultas trayéndote primero una parte de los datos. Cosa distinta es que quieras un AJAX en el que al escribir una ciudad, en el selector de usuarios te aparezcan sólo los de esa ciudad, y en de aparatos, los aparatos relacionados con personas de esa ciudad, y las marcas y modelos de los aparatos... y luego si hay coincidencia en todo, al elegir uno de ellos te aporte todos los datos. Pero esos serían varias consultas dependiendo de los campos en los que se incluyeran datos. No sé si te estoy entendiendo bien.
  #28 (permalink)  
Antiguo 20/09/2012, 11:24
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Jurena, por ahora me sobra con poner solo un dato y darle a buscar.



ajax.php

Código PHP:
Ver original
  1. <?php  
  2. include("conexion.php");
  3. if ($_GET["action"] == "listar")
  4. {
  5.     // valores recibidos por POST
  6.     $vnm   = $_POST['nombre_apellidos'];
  7.     $vpo = $_POST['poblacion'];
  8.     $vte = $_POST['telefono'];
  9.     $vdel  = ($_POST['del'] != '' ) ? explode("/",$_POST['del']) : '';  
  10.     $val   = ($_POST['al']  != '' ) ? explode("/",$_POST['al']) : '';
  11.      
  12.     $sql = "SELECT
  13.    U.nombre,  
  14.               U.apellidos,  
  15.               U.nu_usuario,  
  16.               U.telefono,
  17.    D.poblacion
  18.    FROM USUARIOS U, DIR_USUARIOS D
  19.    WHERE  
  20.    U.NU_USUARIO=D.USUARIO
  21.    AND U.telefono like '%$vte%'";      
  22.                                  
  23.     // Ordenar por
  24.     $vorder = $_POST['orderby'];
  25.      
  26.     if($vorder != ''){
  27.         $sql .= " ORDER BY ".$vorder;
  28.     }
  29.      
  30.     $query = mysql_query($sql);
  31.     $datos = array();
  32.      
  33.     while($row = mysql_fetch_array($query))
  34.     {
  35.         $datos[] = array(
  36.             'nu_usuario'          => $row['nu_usuario'],
  37.             'telefono'          => $row['telefono'],
  38.             'nombre'      => $row['nombre'],
  39.             'apellidos'       => $row['apellidos'],
  40.             'poblacion'        => $row['poblacion'],
  41.             'aparato'          => $row['aparato'],
  42.             'marca'          => $row['marca'],
  43.             'modelo'      => $row['modelo'],
  44.             'num_serie'       => $row['num_serie'],
  45.             'num_producto'        => $row['num_producto'],
  46.             'fecha_compra'        => $row['fecha_compra'],
  47.             'num_aviso'          => $row['num_aviso'],
  48.             'num_usuario'          => $row['num_usuario'],
  49.             'aparato'      => $row['aparato'],
  50.             'calle'       => $row['calle'],
  51.             'fecha_recepcion'        => $row['fecha_recepcion'],
  52.             'fecha_emision'        => $row['fecha_emision'],
  53.             'sintoma'        => $row['sintoma']
  54.         );
  55.     }
  56.     // convertimos el array de datos a formato json
  57.     echo json_encode($datos);
  58. }
  59.  
  60. ?>
  #29 (permalink)  
Antiguo 20/09/2012, 11:47
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Cáceres
Mensajes: 3.735
Antigüedad: 16 años, 1 mes
Puntos: 300
Respuesta: Select para 3 tablas.

Imaginemos que solo buscas la parte de teléfono: Prueba esta consulta primero. Luego iremos añadiendo partes. Claro, esto sólo te traerá nombre, apellidos, nsuario, telefono y poblacion
Código MySQL:
Ver original
  1. •  SELECT
  2. •      U.nombre,  
  3. •                 U.apellidos,  
  4. •                 U.nu_usuario,  
  5. •                 U.telefono,
  6. •      D.poblacion
  7. •      FROM USUARIOS U INNER JOIN DIR_USUARIOS D
  8. •      ON  
  9. •      U.NU_USUARIO=D.USUARIO
  10. •      WHERE U.telefono LIKE '%{$vte}%';
  #30 (permalink)  
Antiguo 20/09/2012, 12:32
Avatar de satjaen  
Fecha de Ingreso: septiembre-2012
Ubicación: Jaén (Andalucía)
Mensajes: 893
Antigüedad: 11 años, 7 meses
Puntos: 10
Respuesta: Select para 3 tablas.

Jurena, ya sería?

SELECT
• U.nombre,
• U.apellidos,
U.num_usuario,
• U.telefono,
• D.poblacion
• FROM USUARIOS U INNER JOIN DIR_USUARIOS D
• ON
U.NUM_USUARIO=D.NUM_USUARIO
• WHERE U.telefono LIKE '%{$vte}%';


no?


- Asi va al 100% en myadmin, mañana te digo como va en web.

Última edición por satjaen; 20/09/2012 a las 12:38

Etiquetas: select
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 04:39.