Объединить несколько дочерних строк в одну строку MYSQL
Заранее спасибо, я просто не могу это понять!
У меня есть две таблицы
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;
Спасибо!
Джо
Ответы
Ответ 1
Самый простой способ - использовать здесь функцию 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;
Ответ 2
Я ценю помощь, я думаю, что нашел решение, если кто-то прокомментирует эффективность, которую я бы оценил. По сути, я сделал это. Я понимаю, что он несколько статичен в своей реализации, но я делаю то, что мне нужно (простить неправильный синтаксис)
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
То, что вы хотите, называется точкой опоры, и оно не поддерживается напрямую в MySQL, проверьте этот ответ на параметры, которые у вас есть:
Как свернуть схему сущностей-атрибутов MySQL
Ответ 4
Если вам действительно нужно несколько столбцов в вашем результате, а количество опций ограничено, вы даже можете сделать это:
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
Ответ 5
Если вы знаете, что у вас будет ограниченное количество максимальных опций, я бы попробовал это (пример для максимум 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 строка для каждого родительского элемента.
Ответ 6
вот как вы могли бы построить свой запрос для этого типа требований.
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 out" в каждом столбце, используя "case when". затем выберите "max()" для каждого из этих столбцов, используя "group by" для каждого предполагаемого элемента.