2

次の列を持つ、単純化された 3 つの MYSQL テーブルがあります。

ModuleEntries (MDE_ID)
ModuleFields (MDF_ID, MDF_Label)
ModuleEntryFieldValues (MFV_ID, MFV_MDE_ID, MFV_MDF_ID, MFV_Value)

単純化された列のリストからわかるようにModuleEntryFieldValues、「エントリの場合、このフィールドにはこの値が含まれる」と記載されている表です。

ここで、この情報を 1 つの "フラット" レコードセットで取得したいと思います。私は物事をうまく機能させることができましたが、完全には望んでいませんでした。

別の SO 記事の助けを借りて、カーソルを使用して、動的で可変量の列を機能させることができました。

  declare finish int default 0;
  declare fldid int;
  declare str varchar(10000) default 'SELECT *,';
  declare curs cursor for select MDF_ID from ModuleFields group by MDF_ID;
  declare continue handler for not found set finish = 1;
  open curs;
  my_loop:loop
    fetch curs into fldid;
    if finish = 1 then
      leave my_loop;
    end if;
    set str = concat(str, 'max(case when MFV_MDF_ID = ',fldid,' then MFV_Value else null end) as field_',fldid,',');
  end loop;
  close curs;
  set str = substr(str,1,char_length(str)-1);
  set @str = concat(str, ' from ModuleEntries LEFT join ModuleEntryFieldValues ON MDE_ID = MDF_MDE_ID GROUP BY MDE_ID');
  prepare stmt from @str;
  execute stmt;
  deallocate prepare stmt;
このコードがしないことは、列の値をMDF_Label行の実際の列ヘッダーとして配置できるようにすることです。さて、上記のコードは「field_1、field_2、...」を提供します

これら3つのテーブルを結合MDF_Labelし、結合されたテーブルの列になっている行の列ヘッダーを使用することは可能ですか?

これ欲しい...

ModuleEntries  |   ModuleFields         |   ModuleEntryFieldValues
-------------  |   ------------------   |   -----------------------------------
MDE_ID         |   MDF_ID - MDF_Label   |   MFV_MDE_ID - MFV_MDF_ID - MFV_Value
1              |   1      - Height      |   1          - 1          - 120cms
               |   2      - Width       |   1          - 2          - 30cms
               |   3      - Weight      |   

これに

Recordset
---------
MDE_ID - Height - Width - Weight
1      - 120cms - 30cms - null

私の質問が十分に明確であることを願っています。そうでない場合は、コメントしてください。可能であれば、必要に応じてさらに情報を提供します。

4

1 に答える 1

3

GROUP_CONCAT()カーソルの代わりに使用して、準備されたステートメントを生成します。

SELECT CONCAT(
 ' SELECT MDE_ID,'

,  GROUP_CONCAT(
     't', MDF_ID, '.MFV_Value AS `', REPLACE(MDF_Label, '`', '``'), '`'
   )

,' FROM ModuleEntries '

, GROUP_CONCAT(
    'LEFT JOIN ModuleEntryFieldValues AS t', MDF_ID, '
       ON t', MDF_ID, '.MFV_MDE_ID = ModuleEntries.MDE_ID
      AND t', MDF_ID, '.MFV_MDF_ID = ', MDF_ID
  SEPARATOR ' ')

) INTO @qry FROM ModuleFields;

空白を編集して読みやすくするために保存します。サンプルデータには次のもの@qryが含まれます。

SELECT MDE_ID,
       t1.MFV_Value AS `Height`,
       t2.MFV_Value AS `Width`,
       t3.MFV_Value AS `Weight`
FROM   ModuleEntries
  LEFT JOIN ModuleEntryFieldValues AS t1
         ON t1.MFV_MDE_ID = ModuleEntries.MDE_ID AND t1.MFV_MDF_ID = 1
  LEFT JOIN ModuleEntryFieldValues AS t2
         ON t2.MFV_MDE_ID = ModuleEntries.MDE_ID AND t2.MFV_MDF_ID = 2
  LEFT JOIN ModuleEntryFieldValues AS t3
         ON t3.MFV_MDE_ID = ModuleEntries.MDE_ID AND t3.MFV_MDF_ID = 3

次に、そのステートメントを準備して実行できます。

PREPARE stmt FROM @qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @qry = NULL;

これにより、次の結果が得られます。

MDE_ID 高さ 幅 重量
     1 120cm 30cm (ヌル)

sqlfiddleで参照してください。

于 2012-05-23T10:12:17.997 に答える