从SQL中的LEFT JOIN创建矩阵/表

时间:2009-07-20 12:32:12

标签: mysql join matrix left-join

我想知道将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。

4 个答案:

答案 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,所以如果数据库类型不匹配,那就是原因。