【问题标题】:Create a matrix/table from a LEFT JOIN in SQL从 SQL 中的 LEFT JOIN 创建矩阵/表
【发布时间】:2009-07-20 12:32:12
【问题描述】:

我想知道将 LEFT JOIN 转换为表/矩阵的好解决方案。

例如,给定这个架构:

对象 id(整数) 名称(字符串) 属性 id(整数) object_id (整数) 名称(字符串) 值(字符串)

还有这些价值观:

1、球 2、盒子 1,1,颜色,红色 2,1,形状,球体 3,1,材料,橡胶 4,2,颜色,棕色 5,2,形状,立方体

我想要这个:

object_id |对象名 |颜色 |形状 |材料 1 |球 |红色 |球体 |橡胶 2 |盒子|棕色 |立方体 |无效的

理想情况下,每个对象都有未知数量的属性,并且在不使用存储过程的情况下用于 MySQL。

【问题讨论】:

    标签: mysql join matrix left-join


    【解决方案1】:

    RDBMSs 的作用在于,它们的目的是存储和展示您已经拥有的东西。从未打算动态创建列。

    这种情况应该在要呈现数据的客户端上处理。

    不管 RDBMS 应该如何使用,您仍然找不到简单的方法来执行此操作。如果您希望列列表是动态的,则尤其如此。您可以构建动态 SQL 查询并执行该查询,但无法编写标准 SQL 查询并获得该结果(因为您始终明确指定所有列,使用* 禁止,但这不能用于您的优势在这种情况下。)

    【讨论】:

      【解决方案2】:

      如果不使用 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 对以及对应的值,您可以在客户端使用它来更轻松地填充矩阵。

      【讨论】:

        【解决方案3】:

        假设结果表被称为合并,这将解决您的问题,尽管您的架构我会说更好。

        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;
        

        【讨论】:

          【解决方案4】:

          嗯,您可能只是缺少 2 个逻辑步骤来实现这一点。

          您需要的是一个 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'
          

          你有它,你应该带回每个具有颜色属性类型和蓝色属性值的对象。

          My Sql 不是那么强大,但如果您想一次搜索多个属性,您应该能够执行多个子句。在我看来,attributes table 中的 attribute_type_id 没有加入 attribute_type 表,但它可以方便在 1 次命中中进行查询,虽然我拥有它,但性能明智,所以它可以通过不必加入来加速查询表,但根据所有内容的大小,差异可能可以忽略不计。

          注意:我通常使用 msssql 而不是 mysql,所以如果数据库类型不匹配,这就是原因。

          【讨论】:

            猜你喜欢
            • 2010-09-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-07-29
            相关资源
            最近更新 更多