2009-07-01 13 views
52

Z góry dziękuję, po prostu nie mogę tego zdobyć!Połączyć wiele wierszy podrzędnych w jednym wierszu MYSQL

Mam dwie tabele

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

Co szukam wyjścia jest zapytanie mysql jest coś w tej sprawie

Wyjście

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

Próbowałem liczne opcje najbardziej zakończenie w błąd składni, próbowałem group_concat ale nie to jest to naprawdę to, co szukam. Mam prosty przykład poniżej tego, co moim zdaniem może być początkiem. Potrzebuję opcji, aby za każdym razem być w tej samej kolejności. A w programie, w którym zbierane są informacje, nie ma możliwości niezawodnego zapewnienia, że ​​tak się stanie. Czy możliwe jest ich łączenie zgodnie z numerem opcji. Ponadto wiem, że nigdy nie będę mieć więcej niż 5 opcji, więc statyczne rozwiązanie zadziała

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; 

Dzięki! Joe

Odpowiedz

90

Najprostszym sposobem byłoby skorzystać z funkcji grupowej GROUP_CONCAT tutaj ..

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 

co wyjściowa:

Id    ItemName  Options 

1    Pizza   Pepperoni,Extra Cheese 

2    Stromboli  Extra Cheese 

W ten sposób można mieć tyle opcji, jak ciebie chcesz bez konieczności modyfikowania zapytania.

Ach, jeśli widzisz wyniki uzyskiwanie przycięta, można zwiększyć limit rozmiaru GROUP_CONCAT tak:

SET SESSION group_concat_max_len = 8192; 
+3

powiedział: "Próbowałem group_concat, ale to naprawdę nie jest to, czego szukam." –

+0

Witam, Dziękuję za szybką odpowiedź, ale obawiam się, że nie podałem ważnej informacji. Potrzebuję opcji, aby za każdym razem być w tej samej kolejności. A w programie, w którym zbierane są informacje, nie ma możliwości niezawodnego zapewnienia, że ​​tak się stanie. Czy możliwe jest ich łączenie zgodnie z numerem opcji. Wiem też, że nigdy nie będę mieć więcej niż 5 opcji, więc rozwiązanie statyczne zadziała. –

+4

Aby zamówić elementy w grupie, można to zrobić na przykład: GROUP_CONCAT (Ordered_Options.Value ORDER BY Ordered_Options.value), –

8

doceniam pomoc, ja sądzę, że znalazł rozwiązanie jeśli ktoś wypowiedzieć się na temat skuteczności bym go docenić. Zasadniczo to, co zrobiłem, jest.Zdaję sobie sprawę, że jest dość statyczna w jego realizacji, ale robi to, co muszę to zrobić (wybacz nieprawidłową składnię)

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

To będzie trudne do utrzymania. Prędzej czy później twój klient będzie chciał mieć trzecią lub czwartą opcję i do tego czasu będziesz musiał przepisać wszystko. –

+0

Dodano kolejną odpowiedź, która daje takie same wyniki, jak opublikowane zapytanie, ale jest nieco bardziej elastyczna. Nadal możesz mieć nieograniczoną liczbę opcji, a jednocześnie uzyskać wiele kolumn opcji dotyczących pizzy w wynikach. –

1

Jeśli naprawdę potrzebujesz wiele kolumn w swojej konsekwencji i ilość opcji jest ograniczona, można nawet to zrobić:

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 
1

Jeśli wiesz, że będziesz mieć ograniczoną liczbę opcji max to bym spróbować tego (przykład dla max 4 opcji na kolejności):

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

sol warunek roup by pozbywa się wszystkich duplikatów, które w przeciwnym razie dostałeś. Właśnie zaimplementowałem coś podobnego na stronie, nad którą pracuję, gdzie wiedziałem, że zawsze mam 1 lub 2 pasujące do mojego stołu podrzędnego, i chciałem mieć pewność, że mam tylko jeden wiersz dla każdego elementu nadrzędnego.

0

Oto jak skonstruować zapytanie dla tego rodzaju wymagań.

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; 

W zasadzie "usuwaj" każdą kolumnę za pomocą "case when". następnie wybierz "max()" dla każdej z tych kolumn, używając "group by" dla każdego zamierzonego elementu.

Powiązane problemy