【问题标题】:Combine Multiple child rows into one row MYSQL将多个子行合并为一行MYSQL
【发布时间】:2010-11-07 05:38:11
【问题描述】:

在此先感谢,我似乎无法得到它!

我有两张桌子

Ordered_Item

ID |项目名称
1 |比萨
2 |斯特龙博利

Ordered_Options

Ordered_Item_ID |选项号码 |价值
        1 43​​ 意大利辣香肠
        1 44 额外的奶酪
        2 44 额外的奶酪

我想要输出的是一个 mysql 查询就是这样的结果

输出

ID |物品名称 |选项_1 |选项_2
1 份披萨意大利辣香肠额外奶酪
2 Stromboli NULL 额外奶酪

我尝试了许多以语法错误结尾的选项,我尝试了 group_concat 但这并不是我真正想要的。我在下面有一个粗略的例子,我认为这可能是一个开始。我需要每次都以相同的顺序排列选项。在收集信息的程序中,没有办法可靠地确保会发生这种情况。是否可以根据选项编号将它们连接起来。我也知道我永远不会有超过 5 个选项,所以静态解决方案会起作用

Select Ordered_Items.ID,
    Ordered_Items.Item_Name,
FROM Ordered_Items
    JOIN (SELECT Ordered_Options.Value FROM Ordered_Options Where Option_Number = 43) as Option_1 
        ON Ordered_Options.Ordered_Item_ID = Ordered_Item.ID
    JOIN (SELECT Ordered_Options.Value FROM Ordered_Options Where Option_Number = 44) as Option_2 
        ON Ordered_Options.Ordered_Item_ID = Ordered_Item.ID;

谢谢! 乔

【问题讨论】:

    标签: mysql select join


    【解决方案1】:

    Joe Edel 对自己的回答实际上是解决支点问题的正确方法。

    基本上这个想法是首先列出基表中的列,然后从联合选项表中列出任意数量的options.value。只需多次left join 同一个选项表即可获得所有选项。

    编程语言需要做的是根据需要查询的选项列表动态构建这个查询。

    【讨论】:

      【解决方案2】:

      以下是针对此类需求构建查询的方式。

      select ID,Item_Name,max(Flavor) as Flavor,max(Extra_Cheese) as Extra_Cheese
          from (select i.*,
                          case when o.Option_Number=43 then o.value else null end as Flavor,
                          case when o.Option_Number=44 then o.value else null end as Extra_Cheese
                      from Ordered_Item i,Ordered_Options o) a
          group by ID,Item_Name;
      

      您基本上使用case when“排除”每一列,然后为每个预期项目使用group by 为每一列选择max()

      【讨论】:

        【解决方案3】:

        如果您的结果确实需要多列,并且选项数量有限,您甚至可以这样做:

        select
          ordered_item.id as `Id`,
          ordered_item.Item_Name as `ItemName`,
          if(ordered_options.id=1,Ordered_Options.Value,null) as `Option1`,
          if(ordered_options.id=2,Ordered_Options.Value,null) as `Option2`,
          if(ordered_options.id=43,Ordered_Options.Value,null) as `Option43`,
          if(ordered_options.id=44,Ordered_Options.Value,null) as `Option44`,
          GROUP_CONCAT(if(ordered_options.id not in (1,2,43,44),Ordered_Options.Value,null)) as `OtherOptions`
        from
          ordered_item,
          ordered_options
        where
          ordered_item.id=ordered_options.ordered_item_id
        group by
          ordered_item.id
        

        【讨论】:

          【解决方案4】:

          感谢您的帮助,我认为我已经找到了解决方案,如果有人评论其有效性,我将不胜感激。基本上我所做的是。我意识到它的实现有些静态,但我做了我需要它做的事情(请原谅不正确的语法)

          SELECT
            ordered_item.id as `Id`,
            ordered_item.Item_Name as `ItemName`,
            Options1.Value
            Options2.Value
          FROM ORDERED_ITEMS
          LEFT JOIN (Ordered_Options as Options1)
              ON (Options1.Ordered_Item.ID = Ordered_Options.Ordered_Item_ID 
                  AND Options1.Option_Number = 43)
          LEFT JOIN (Ordered_Options as Options2)
              ON (Options2.Ordered_Item.ID = Ordered_Options.Ordered_Item_ID
                  AND Options2.Option_Number = 44);
          

          【讨论】:

          • 这将很难维护。迟早你的客户会想要第 3 或第 4 选项,到那时你需要重写所有内容。
          • 添加了另一个答案,它给出了与您发布的查询相同的结果,但它更灵活一些。您仍然可以拥有无​​限数量的选项,同时仍然会在结果中为披萨选项提供多列。
          【解决方案5】:

          如果您知道您的最大选项数量有限,那么我会试试这个(例如每个订单最多 4 个选项):

          选择 OI.ID、OI.Item_Name、OO1.Value、OO2.Value、OO3.Value、OO4.Value
          
          FROM Ordered_Items OI
              左连接 Ordered_Options OO1 ON OO1.Ordered_Item_ID = OI.ID
              左连接 Ordered_Options OO2 ON OO2.Ordered_Item_ID = OI.ID AND OO2.ID != OO1.ID
              左连接 Ordered_Options OO3 ON OO3.Ordered_Item_ID = OI.ID AND OO3.ID != OO1.ID AND OO3.ID != OO2.ID
              左连接 Ordered_Options OO4 ON OO4.Ordered_Item_ID = OI.ID AND OO4.ID != OO1.ID AND OO4.ID != OO2.ID AND OO4.ID != OO3.ID
          
          按 OI.ID、OI.Item_Name 分组

          按条件分组会消除您原本会得到的所有重复项。我刚刚在我正在开发的网站上实现了类似的东西,我知道我的子表中总是有 1 或 2 个匹配项,并且我想确保每个父项只有 1 行。

          【讨论】:

            【解决方案6】:

            最简单的方法是在这里使用 GROUP_CONCAT 组函数..

            select
              ordered_item.id as `Id`,
              ordered_item.Item_Name as `ItemName`,
              GROUP_CONCAT(Ordered_Options.Value) as `Options`
            from
              ordered_item,
              ordered_options
            where
              ordered_item.id=ordered_options.ordered_item_id
            group by
              ordered_item.id
            

            哪个会输出:

            Id              ItemName       Options
            
            1               Pizza          Pepperoni,Extra Cheese
            
            2               Stromboli      Extra Cheese
            

            这样您就可以拥有任意数量的选项,而无需修改您的查询。

            啊,如果你看到你的结果被裁剪了,你可以像这样增加 GROUP_CONCAT 的大小限制:

            SET SESSION group_concat_max_len = 8192;
            

            【讨论】:

            • 他说“我已经尝试过 group_concat,但这并不是我真正想要的。”
            • 您好,感谢您的快速回复,但恐怕我没有提供重要信息。我需要每次都以相同的顺序排列选项。在收集信息的程序中,没有办法可靠地确保会发生这种情况。是否可以根据选项编号将它们连接起来。我也知道我永远不会有超过 5 个选项,所以静态解决方案会起作用。
            • 要对组内的项目进行排序,例如:GROUP_CONCAT(Ordered_Options.Value ORDER BY Ordered_Options.value),
            • 如果计数有误,请尝试DISTINCT 计数,即SELECT count(DISTINCT u.id) as totalRecords
            【解决方案7】:

            您想要的称为枢轴,并且 MySQL 不直接支持它,请查看此答案以了解您所拥有的选项:

            How to pivot a MySQL entity-attribute-value schema

            【讨论】:

              猜你喜欢
              • 2012-08-29
              • 2014-02-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-06-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多