将多个子行合并为一行MYSQL


74

在此先感谢,我似乎无法理解!

我有两张桌子

Ordered_Item

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

Ordered_Options

Ordered_Item_ID | Option_Number | 值
        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;

谢谢!乔

Answers:


124

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

3
他说:“我尝试过group_concat,但这并不是我真正想要的。”
Haim Evgi,2009年

您好,感谢您的快速回复,但恐怕我没有提供重要的信息。我需要选项每次都按相同顺序排列。并且在收集信息的程序中,没有办法可靠地确保将要发生。是否可以根据选件号将它们连接在一起。我也知道我永远不会有超过5个选择,因此静态解决方案将起作用。

4
要订购组中的项目,您可以例如执行以下操作:GROUP_CONCAT(Ordered_Options.Value ORDER BY Ordered_Options.value),
Wouter van Nifterick,2009年

14

感谢您的帮助,我认为如果有人对我的效果表示赞赏,我已经找到了解决方案。本质上,我所做的就是。我意识到它的实现有些静态,但是我做了我需要做的事情(原谅不正确的语法)

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

6
这将很难维护。您的客户迟早会希望拥有第3个或第4个选项,然后您需要重写所有内容。
Wouter van Nifterick,2009年

添加了另一个答案,该答案的结果与您发布的查询相同,但更加灵活。您仍然可以有无限数量的选项,同时在结果中仍然会获得披萨选项的多列。
Wouter van Nifterick,2009年

5

如果您的结果中确实需要多列,并且选项数量有限,则可以执行以下操作:

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

如果您知道有限数量的最大选项,那么我会尝试一下(例如每个订单最多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和OO2.ID!= OO1.ID
    左联接Ordered_Options OO3 ON OO3.Ordered_Item_ID = OI.ID和OO3.ID!= OO1.ID和OO3.ID!= OO2.ID
    左联接Ordered_Options OO4 ON OO4.Ordered_Item_ID = OI.ID和OO4.ID!= OO1.ID和OO4.ID!= OO2.ID和OO4.ID!= OO3.ID

OI.ID,OI.Item_Name的分组

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



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


-2

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.