Nueva pregunta

Pregunta:

 
  0  
 
Fecha: 03-07-2018 05:03:31 (En Español)

Consulta MySQL varias tablas[Resuelta]

Hola compañeros.

Necesito hacer una consulta que en algún lado estoy haciendo mal. Me explico:

Tengo 2 tablas, la tabla LAYOUTS que son productos y la tabla LAYOUTS_TAGS que son características de esos productos, y en el buscador cuando busco me dice que no hay resultados y no se si es por el INNER JOIN que lo estoy haciendo mal o que... por ejemplo:

SELECT l.* FROM layouts l INNER JOIN layouts_tags lt ON l.id = lt.layout_id AND lt.tag_id = 1 AND lt.tag_id = 21 AND lt.tag_id = 3 WHERE l.visible = 1 ORDER BY l.priority DESC, l.discontinued ASC, l.updated_at DESC

En esa consulta en el buscador he marcado 3 tags, y se que corresponden con un producto pero me dice que no hay resultados... no me da fallo ni nada...

Que hago mal?

Desde ya muchas gracias.
Etiquetas: Base de Datos - MySQL - Pregunta - Query - SQL Votos: 0 - Respuestas: 8 - Vistas: 20 Compartir en: Google Facebook Twitter LinkedIn Link
 

Respuestas:

  • Fecha: 03-07-2018 06:18:54 Fran
    Buenas tardes

    Sigue este ejemplo

    SELECT column_name(s)
    FROM table1
    INNER JOIN table2 ON table1.column_name = table2.column_name;

    Suerte
      Votos: 1 - Link respuesta
     
  • Fecha: 03-07-2018 09:56:41 Hola Fran,

    INNER JOIN (unir internamente) selecciona los registros que tengan correspondencia en ambas tablas, dicho de manera contraria, excluye todos aquellos registros que no tienen correspondencia.

    Cuando en la condición ON del JOIN añades más condiciones como es tu caso, debes tener en cuenta que obtendrás los registros que cumplan con TODAS esas condiciones:

    a) ON I.id = It.layout_id (que el id de la tabla I corresponda con el id_layout de la tabla It)
    b) AND It.tag_id = 1 ( Y cuando It.tag_id sea 1 )
    c) AND It.tag_id = 21 ( Y cuando It.tag_id sea 21 )
    d) AND It.tag_id = 3 ( Y cuando It.tag_id sea 3 )

    Claramente, las últimas tres condiciones (b, c, d) son ilógicas: se excluyen entre si. It.tag_id puede ser 1, 21 o 3 pero nunca los tres al mismo tiempo.

    Prueba con esto:

    ... ON I.id = It.layout AND (It.tag_id = 1 OR It.tag_id = 21 OR It.tag_id = 3) ...

    Con esto le indicas que haga la unión siempre y cuando It.tag_id sea alguno de esos valores.

    De cualquier manera, eso es complicar el JOIN. Aunque puede hacerse, no es eficiente condicionar JOIN ... ON más allá de lo que está condicionado.

    Suerte y me avisas cómo te ha ido.
      Votos: 3 - Link respuesta
     
  • Fecha: 03-07-2018 11:31:55 Checa la respuesta de Leonardo pero en vez de:

    ON I.id = It.layout AND (It.tag_id = 1 OR It.tag_id = 21 OR It.tag_id = 3)

    Haz:

    ON I.id = It.layout AND It.tag_id IN (1,3,21)

    Que hace lo mismo pero es mas sencillo de leer

    Saludos
      Votos: 2 - Link respuesta
     
  •  
      0  
     
    Fecha: 03-07-2018 20:50:41 Hola de nuevo compañeros.

    Leonardo Montilla, muchas gracias por tu respuesta. La consulta no es ilógica puesto que son características del producto y puede tener una característica o 10000, por lo tanto si quiero buscar un producto que tenga esas 3 características se debe poder hacer de alguna manera.

    Erenesto Peimbert, muchas gracias por tu respuesta. La consulta la hice la primera vez exactamente como tu dices, pero mi jefe me dijo que en los resultados le aparecían productos que contenían cualquiera de esas 3 características, y el quiere en el buscador que le aparezcan productos que tengan las 3 características o 4 o las que seleccione, pero que las tengan todas no solo una. Por eso modifiqué la consulta a la que he puesto en la pregunta pensando que me funcionaría pero no me funciona.

    ¿Alguna otra sugerencia compañeros?
      Votos: 0 - Link respuesta
     
  • Fecha: 04-07-2018 04:42:08 Hola Fran,

    Comprendo. En ese caso solo te quedan dos soluciones: (a) hacer la consulta completa con el JOIN principal y recorrer el resultado para filtrar lo que quieres o (b) crear un JOIN por cada característica.

    Sospecho que lo de las características puede variar, así que la opción (b) no es la adecuada. Haz la consulta general y luego filtra recorriendo todo el resultado:

    SELECT l.*, It.tag_id FROM layouts l INNER JOIN layouts_tags lt ON l.id = lt.layout_id WHERE l.visible = 1 ORDER BY l.priority DESC, l.discontinued ASC, l.updated_at DESC

    ...

    
    while($row = $consulta->fetch()) {  // (no sé cuál librería usas, esto es para PDO
        if($row['tag_id'] == 1 || $row['tag_id'] == 21 || $row['tag_id'] == 3) {
          // acá haces lo que necesites con esos registros
        }
    }
    


    Esto puede ser un poquito más lento, pero es imperceptible (a menos que hables de millones de registros)

    Saludos.
      Votos: 1 - Link respuesta
     
  •  
      0  
     
    Fecha: 04-07-2018 20:39:53 Muchas gracias Leonardo, entonces... entiendo que no es posible realizar una consulta de la manera que quiero? sin necesidad de realizar acciones con PHP?
    En caso que sea imposible.... de qué manera deberían haber estados construidas las tablas para poder hacer esto con una sola consulta?, ya que pienso que esto es algo habitual...
    Gracias de nuevo.
      Votos: 0 - Link respuesta
     
  • Fecha: 09-07-2018 07:35:23 Disculpa la demora en responder. Estoy asumiendo que la tabla "layouts_tag" es una tabla de unión (layouts y tags), en ese caso es la mejor solución que tienes y si la búsqueda que intentas es hallar los productos con mismas características, lo anterior es lo más adecuado dado que la cantidad de características no es finita. Nada más que hacer o al menos no se me ocurre. Sería interesante ver una solución mejor.   Votos: 0 - Link respuesta
     
  •  
      0  
     
    Fecha: 09-07-2018 20:54:04 Hola de nuevo a todos compañeros...

    Ya he solucionado la consulta... y por lo tanto lo comparto aquí por si alguien en algún momento le sucede lo mismo puedan ver la solución.

    SOLUCIÓN 1:
    SELECT l.*
    FROM layout l
    INNER JOIN layout_tag lt
    ON l.id = lt.layout_id
    WHERE lt.tag_id IN (aqui los id de las tags separadas por comas)
    GROUP BY l.name
    HAVING COUNT(DISTINCT lt.tag_id) = numero de tags que hayan seleccionado

    SOLUCIÓN 2:
    SELECT *
    FROM layout.l
    RIGHT JOIN layout_tag lt ON l.id = lt.layout_id AND lt.tag_id = x
    RIGHT JOIN layout_tag lt1 ON l.id = lt1.layout_id AND lt.tag_id = y
    RIGHT JOIN layout_tag lt2 ON l.id = lt2.layout_id AND lt.tag_id = z
    ... así por cada tag que se haya seleccionado.

    Muchas gracias a todos por vuestras respuestas.
      Votos: 0 - Link respuesta
     
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión
 
frjcbbae garagebible.com