Подтвердить что ты не робот

Объединить несколько дочерних строк в одну строку 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;

Спасибо! Джо

4b9b3361

Ответ 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);

Ответ 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" для каждого предполагаемого элемента.