我想知道将LEFT JOIN转换为表/矩阵的好方法。
例如,给定此架构:
objects id (integer) name (string) attributes id (integer) object_id (integer) name (string) value (string)
这些价值观:
1,ball 2,box 1,1,colour,red 2,1,shape,sphere 3,1,material,rubber 4,2,colour,brown 5,2,shape,cube
我想得到这个:
object_id | object_name | colour | shape | material 1 | ball | red | sphere | rubber 2 | box | brown | cube | NULL
理想情况下,每个对象的属性数量都是未知的,不使用存储过程就是MySQL。
答案 0 :(得分:1)
如果不在SQL
中使用动态查询,则无法执行此操作。
任何集合SQL
处理都假设固定数量的列具有固定名称。
否则会导致许多事情SQL
无法解决。
就像想象一下在您要求的查询上创建的视图(是否可能):
SELECT object_id, colour
FROM myquery
这个视图是否编译将取决于查询的结果,这会给你运行时错误(很难处理),而不仅仅是空结果集(很容易处理)。
您基本上是在谈论此处的结果演示文稿,这些内容通常在客户端完成。
如果您的attribute_names
表包含所有可能的属性名称,则可以执行以下操作:
SELECT o.name, an.name, a.value
FROM objects o
CROSS JOIN
attribute_names an
LEFT JOIN
attributes a
ON a.object = o.id
AND a.name = an.name
,它将包含具有相应值的所有可能的object_id / attribute_name
对,您可以在客户端使用它来更轻松地填充矩阵。
答案 1 :(得分:1)
RDBMS的问题是他们的目的是存储和展示你已经拥有的东西。动态创建列从未打算过。
这是应在要呈现数据的客户端上处理的情况。
无论如何使用RDBMS,您仍然无法找到一种简单的方法。特别是如果您希望列列表是动态的。您可以构建一个动态SQL查询并执行该查询,但是无法编写标准SQL查询并获得该结果(因为您始终明确指定所有列,使用*
禁止,但不能用于在这种情况下你的优势。)
答案 2 :(得分:0)
这可以解决你的问题,假设结果表被称为合并,虽然我所说的模式更好。
insert into merged (object_id, object_name) select id, name from objects;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'colour' set m.colour = a.value;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'material' set m.material = a.value;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'shape' set m.shape = a.value;
答案 3 :(得分:0)
嗯,这可能是你错过了两个合乎逻辑的步骤来实现这一目标。
您需要的是AttributeTypes表和AttributeValues表。
objects
id (integer)
name (string)
attribute_types
id (integer)
name (string)
description (string)
enabled (bit)
attribute_values
id (integer)
attribute_type_id (integer)
value (string)
enabled (bit)
attributes
id (integer)
object_id (integer)
attribute_type_id (integer)
attribute_value_id (integer)
因此,对象可以具有属性,这些属性由attribute_type_id和attribute_value_id指定。
然后,这允许您拥有一个具有多个属性的对象..
例如
object
-> 1, ball
attribute_types
-> 10, Colour, null, enabled
-> 20, Shape, null, enabled
-> 30, Material, null, enabled
attribute_values
-> 100, 10, blue, enabled
-> 200, 10, red, enabled
-> 300, 10, green, enabled
-> 400, 20, round, enabled
-> 500, 20, square, enabled
-> 600, 20, triangle, enabled
所以属性看起来像:
attributes
-> 1000, 1, 10, 100 // this item has a color and it is blue
-> 1001, 1, 20, 400 // this item has a shape and it is round
-> 1002, 1, 10, 200 // this item has a color and it is red
所以现在对象可以有多个属性,这些属性在不同的表中指定它们的值。现在重要的问题是如何查询的?您可能必须根据sql的强大程度将查询拆分为多个部分。
@attribute_type_id = select Id from attribute_types where name = 'Color' // 10
select * from objects
inner join attributes on objects.id = attributes.object_id
inner join attribute_values on objects.attribute_value_id = attribute_values.id
where attribute_type_id = @attribute_type_id
and attribute_values.value= 'blue'
你有它你应该带回每个具有color_type为color和attribute_value为蓝色的对象。
我的Sql不是那么强大但如果你想一次搜索多个属性,你应该可以做多个子句。在我看来,属性表中的attribute_type_id没有加入到attribute_type表中,但它可以方便地在1次点击中进行查询,虽然我已经拥有它,但是它可以通过不必加入一个来加速查询。表格,但差异可能是微不足道的,取决于一切都有多大。
注意:我通常使用msssql而不是mysql,所以如果数据库类型不匹配,那就是原因。