Hola aovalle:
Complementando el comentario de quimfv, el utilizar funciones de agrupación (MAX, MIN, SUM) es una manera "tramposa" de hacerlo, ya que de entrada puedo suponer que el campo valor_atributo es de tipo VARCHAR, ya que almacenas tanto valores como cadenas y valores nulos... de tal forma que el resultado puede ser un tanto impredecible... hay otra forma de obtener el mismo resultado utilizando LEFT JOIN's sobre la tabla de atributoslibros, utilizando alias, de esta manera:
Código MySQL:
Ver original+----------+-------------+
| id_libro | titulolibro |
+----------+-------------+
| 1 | Odisea |
| 2 | Soledad |
+----------+-------------+
+----------+-------------+----------------+
| id_libro | id_atributo | valor_atributo |
+----------+-------------+----------------+
| 1 | 1 | 10000 |
| 1 | 2 | 1980 |
| 1 | 3 | 1 |
| 1 | 4 | Rustico |
| 2 | 1 | 0 |
| 2 | 2 | 1945 |
| 2 | 4 | Tapa dura |
+----------+-------------+----------------+
-> l.id_libro,
-> l.titulolibro,
-> alPrecio.valor_atributo precio,
-> alFecha.valor_atributo fecha,
-> alVolumen.valor_atributo volumen,
-> alEmpaste.valor_atributo empaste
-> ON l.id_libro
= alPrecio.id_libro
AND alPrecio.id_atributo
= 1 -> ON l.id_libro
= alFecha.id_libro
AND alFecha.id_atributo
= 2 -> ON l.id_libro
= alVolumen.id_libro
AND alVolumen.id_atributo
= 3 -> ON l.id_libro
= alEmpaste.id_libro
AND alEmpaste.id_atributo
= 4; +----------+-------------+--------+-------+---------+-----------+
| id_libro | titulolibro | precio | fecha | volumen | empaste |
+----------+-------------+--------+-------+---------+-----------+
| 1 | Odisea | 10000 | 1980 | 1 | Rustico |
| 2 | Soledad
| 0 | 1945 | NULL | Tapa dura
| +----------+-------------+--------+-------+---------+-----------+
Tal como te menciona quimfv en su post, el problema es que la asignación de los alias para cada columna lo estoy haciendo de manera arbitraria, es decir sin tomar en cuenta el contenido del catálogo de atributos. Finalmente, puedes simplificar la consulta de quimfv sin necesidad de utilizar subconsultas, asi:
Código MySQL:
Ver original -> l.id_libro,
-> l.titulolibro,
-> MAX(IF(a.id_atributo
= 1, a.valor_atributo
, NULL)) precio
, -> MAX(IF(a.id_atributo
= 2, a.valor_atributo
, NULL)) fecha
, -> MAX(IF(a.id_atributo
= 3, a.valor_atributo
, NULL)) volumen
, -> MAX(IF(a.id_atributo
= 4, a.valor_atributo
, NULL)) empaste
+----------+-------------+--------+-------+---------+-----------+
| id_libro | titulolibro | precio | fecha | volumen | empaste |
+----------+-------------+--------+-------+---------+-----------+
| 1 | Odisea | 10000 | 1980 | 1 | Rustico |
| 2 | Soledad
| 0 | 1945 | NULL | Tapa dura
| +----------+-------------+--------+-------+---------+-----------+
Repitiendo, que el uso de la función MAX sobre un campo tipo varchar puede traer problemas.
Finalmente, podrías optar por cambiar el modelo de BD, después de todo no creo que los atributos de un libro sean muchos aparte de estos... podrías cambiar a un modelo con sólo dos tablas:
Código MySQL:
Ver original+----------+-------------+
| id_libro | titulolibro |
+----------+-------------+
| 1 | Odisea |
| 2 | Soledad |
+----------+-------------+
+----------+--------+-------+---------+-----------+
| id_libro | precio | fecha | volumen | empaste |
+----------+--------+-------+---------+-----------+
| 1 | 10000 | 1980 | 1 | Rustico |
| 2 | 0 | 1945 | NULL | Tapa dura
| +----------+--------+-------+---------+-----------+
Podrías agregar una columna de comentarios para agregar atributos adicionales... podrías definir tus campos precio, fecha y volumen de tipo numérico, lo que te permitiría obtener consultas por ejemplo de rangos de precios o de años en específicos (cosa que con tu modelo no lo podrías hacer).
Saludos
Leo.