web-dev-qa-db-ja.com

複数の子行を1つの行MYSQLに結合します

事前に感謝します、私はちょうどそれを得ることができないようです!

2つのテーブルがあります

Ordered_Item

ID | Item_Name 
 1 |ピザ
 2 |ストロンボリ

注文オプション

Ordered_Item_ID |オプション番号|値
 1 43ペパロニ
 1 44追加チーズ
 2 44追加チーズ

私が出力しようとしているのは、mysqlクエリがこの効果に何か

出力

ID | Item_Name | Option_1 | Option_2 
 1ピザペパロニエクストラチーズ
 2ストロンボリ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;

ありがとう!ジョー

62
Joe Edel

最も簡単な方法は、ここで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;
106

私は助けに感謝します、誰かが私がそれを感謝する有効性についてコメントするならば、私は解決策を見つけたと思います。基本的に私がしたことは。私はそれが実装で多少静的であることを理解していますが、私はそれを行うために必要なことを行います(間違った構文を許してください)

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);
9
Joe Edel

結果に複数の列が本当に必要であり、オプションの量が限られている場合は、これを行うこともできます。

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つのオプションの例):

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 
 LEO 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およびOO3.ID!= OO2.ID 
左結合Ordered_Options OO4 ON OO4.Ordered_Item_ID = OI.IDおよびOO4.ID!= OO1.IDおよびOO4.ID!= OO2.ID AND OO4.ID!= OO3.ID 
 
 GROUP BY OI.ID、OI.Item_Name

Group by条件は、そうでなければ取得する重複のすべてを取り除きます。作業中のサイトで、子テーブルで常に1つまたは2つ一致することがわかっているサイトに同様のものを実装しました。親アイテムごとに1行のみを確保したかったのです。

1
Seb

このタイプの要件に対してクエリを作成する方法を次に示します。

_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()を選択します。

1
ck.tan

あなたが望むものはピボットと呼ばれ、MySQLでは直接サポートされていません。あなたが持っているオプションについてはこの答えをチェックしてください:

MySQLエンティティ属性値スキーマをピボットする方法

1
Vinko Vrsalovic