将多个子行组合成一行MYSQL

时间:2009-07-01 05:34:51

标签: mysql select join

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

我有两张桌子

Ordered_Item

ID | Item_Name
1  | Pizza
2  | Stromboli

Ordered_Options

Ordered_Item_ID | Option_Number | Value
        1               43         Pepperoni
        1               44         Extra Cheese
        2               44         Extra Cheese

我想要输出的是mysql查询就是这种效果

输出

ID | Item_Name | Option_1 | Option_2
1    Pizza       Pepperoni  Extra Cheese
2    Stromboli     NULL     Extra Cheese

我尝试了很多以语法错误结尾的选项,我尝试过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;

谢谢! 乔

7 个答案:

答案 0 :(得分:101)

最简单的方法是在这里使用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;

答案 1 :(得分:9)

我很感激帮助,我认为如果有人评论我会感激的有效性,我会找到解决方案。基本上我做的是。我意识到它的实现有点静态,但我做了我需要做的事情(原谅不正确的语法)

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);

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

你想要的是一个支点,它不是MySQL直接支持的,请查看你已经获得的选项的答案:

How to pivot a MySQL entity-attribute-value schema

答案 4 :(得分:1)

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

Select OI.ID, OI.Item_Name, OO1.Value, OO2.Value, OO3.Value, OO4.Value

FROM Ordered_Items OI
    LEFT JOIN Ordered_Options OO1 ON OO1.Ordered_Item_ID = OI.ID
    LEFT JOIN Ordered_Options OO2 ON OO2.Ordered_Item_ID = OI.ID AND OO2.ID != OO1.ID
    LEFT JOIN Ordered_Options OO3 ON OO3.Ordered_Item_ID = OI.ID AND OO3.ID != OO1.ID AND OO3.ID != OO2.ID
    LEFT JOIN 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

GROUP BY OI.ID, OI.Item_Name

按条件分组可以消除您可能获得的所有重复项。我刚刚在我正在工作的网站上实现了类似的东西,我知道在我的子表中我总是有1或2个匹配,我想确保每个父项只有1行。

答案 5 :(得分:1)

以下是为这类要求构建查询的方法。

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“排除”每列,然后针对每个目标项目使用max()为每个列选择group by

答案 6 :(得分:0)

乔·埃德尔对自己的回答实际上是解决关键问题的正确方法。

基本上,这个想法是首先列出基础表中的列,然后列出联合选项表中的任意数量的options.value。多次left join相同的选项表才能获得所有选项。

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