将多个子行合并为一行MYSQL
Posted
技术标签:
【中文标题】将多个子行合并为一行MYSQL【英文标题】:Combine Multiple child rows into one row 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;
谢谢! 乔
【问题讨论】:
【参考方案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
【讨论】:
以上是关于将多个子行合并为一行MYSQL的主要内容,如果未能解决你的问题,请参考以下文章