MySQL display records from one table as columns from another

2

I have a table articulos

-------------------------  
|id|descripcion|color   |  
|--|-----------|--------|  
|1 |caja       |rojo    |  
|2 |baul       |azul    |  
|3 |cofre      |amarillo|  
-------------------------

And another table atributos

---------------------------  
|id |id_art|nombre |valor |
|---|------|-------|------|  
|1  |1     |alto   |150   |
|2  |1     |ancho  |300   |
|3  |1     |peso   |12    |
|4  |1     |stock  |8     |
|5  |2     |alto   |100   |
|6  |2     |ancho  |200   |
|7  |2     |peso   |10    |
|8  |3     |ancho  |300   |
---------------------------

What I need is by means of a query of query, to obtain that the attributes of an article behave like columns to filter by the values of the same, that is to say:

-----------------------------------------------  
|id|descripcion|color   |alto|ancho|peso|stock|  
|--|-----------|--------|----|-----|----|-----|  
|1 |caja       |rojo    |150 |300  |12  |8    |  
|2 |baul       |azul    |100 |200  |10  |null |  
|3 |cofre      |amarillo|null|300  |null|null |  
-----------------------------------------------

to thus filter by them or show them.
select * from articulos where alto = 150 and ancho = 300

Thank you in advance.

    
asked by Marcelo R 11.07.2017 в 18:32
source

4 answers

0

I got the list you need, with the instruction case when and sum

select ar.id, ar.descripcion, ar.color, 
  sum(case when at.nombre = "alto"  then valor end) as alto,
  sum(case when at.nombre = "ancho" then valor end) as ancho,
  sum(case when at.nombre = "peso"  then valor end) as peso,
  sum(case when at.nombre = "stock" then valor end) as stock 
from articulos ar inner join atributos at
              on ar.id = at.id_art 
group by 1,2,3 ;
    
answered by 12.07.2017 / 21:19
source
0

Good, the most accessible solution to your problem (to my way of seeing) is to perform a JOIN, (you can get more information about JOIN types here ). Note that if you had organized the column by assigning the name and then giving the values (respecting the id of articles), it would be much simpler (and logical).

Basically the query (that comes to mind) that most closely approximates what you want is:

SELECT * FROM articulos JOIN atributos ON articulos.id = atributos.id_art WHERE atributos.id_art = 1 AND IF (atributos.nombre = 'alto' AND atributos.valor = 150,TRUE,FALSE) OR IF(atributos.nombre = 'ancho' AND atributos.valor = 300,TRUE,FALSE)

The answer to this query (based on the data in your table) are the values: width = 300 and height = 150 (see image), confirming that these values exist for the article (id.art) 1.

Graphic example (click on the image to see better):

That is, for this case, the box complies with the two attributes, since if it did not have, for example, a height of 150, only width = 300 would appear, confirming that it does not meet both requirements.

That is, it works 'in reverse'.

    
answered by 11.07.2017 в 19:54
0
  • In SQL there is no way, by queries, of transposing the rows into columns.
  • If what you want is to filter by a where you can solve it by means of the following query:

    SELECT a.Id, a.descripcion, a.color, a2.nombre, a2.valor  
    FROM articulos AS a
    INNER JOIN atributos AS a2
        ON (a.Id = a2.Id_art)
    WHERE (a2.nombre = 'alto' and a2.valor = 150) or 
        (a2.nombre = 'ancho' and a2.valor = 300)
    
  • The result would be obtained in rows with the attributes one below the other for each article. If you need it transposed, you can take it to excel and use a dynamic table. Greetings.

    NEW RESPONSE If you need to meet both conditions with different attributes, you use subqueries:

    SELECT a.Id, a.descripcion, a.color, a2.nombre, a2.valor  
    FROM articulos AS a
    INNER JOIN atributos AS a2
        ON (a.Id = a2.Id_art)
    WHERE ( SELECT COUNT(*) 
            FROM atributos AS a3
            WHERE a.Id = a3.Id_art AND 
                a3.nombre = 'alto' AND 
                a3.valor = 150) >=1  AND 
          ( SELECT COUNT(*) 
            FROM atributos AS a3
            WHERE a.Id = a3.Id_art AND 
                a3.nombre = 'ancho' and 
               a3.valor = 300) >=1
    

    Subqueries count the records where your conditions are met in the attributes, if they give greater than or equal to 1 in each of them, it fulfills the condition you are looking for.

        
    answered by 11.07.2017 в 18:52
    0

    You need a Double Join

  • You get the articles that are high in 150
  • Of the items obtained, get those that have the width in 300

    SELECT art.Id, art.description, art.color, a_alto.name, a_alto.value
        FROM articles AS art     INNER JOIN attributes AS a_alto ON         a_alto.Id = art.Id_art AND         a_alto.nombre = 'high' AND         a_alto.valor = 150
        INNER JOIN attributes AS a_ancho ON         a_ancho.Id = art.Id_art AND         a_ancho.nombre = 'wide' AND         a_ancho.valor = 300

  • answered by 12.07.2017 в 20:42