web-dev-qa-db-ja.com

動的列の行への転置

Table_1Expected_Result_Tableにピボット解除する方法を知りたいのですが。

Table1
-----------------------------------------
Id       abc  brt ccc ddq eee fff gga hxx
-----------------------------------------
12345     0    1   0   5   0   2   0   0  
21321     0    0   0   0   0   0   0   0   
33333     2    0   0   0   0   0   0   0   
41414     0    0   0   0   5   0   0   1   
55001     0    0   0   0   0   0   0   2   
60000     0    0   0   0   0   0   0   0 
77777     9    0   3   0   0   0   0   0
Expected_Result_Table
---------------------
Id      Word   Qty>0
---------------------
12345    brt    1
12345    ddq    5
12345    fff    2
33333    abc    2
41414    eee    5
41414    hxx    1
55001    hxx    2
77777    abc    9
77777    ccc    3

では、0より大きい値のみを考慮して、Table_1の列を転置してExpected_Result_Tableにする方法は?

15
Romualdo Alves

MySQLにはUNPIVOT関数はありませんが、UNION ALLを使用して列を行に変換できます。

基本的な構文は次のとおりです。

select id, Word, qty
from
(
  select id, 'abc' Word, abc qty
  from yt
  where abc > 0
  union all
  select id, 'brt', brt
  from yt
  where brt > 0
) d
order by id;

あなたの場合、動的列のソリューションが必要であると述べています。その場合は、プリペアドステートメントを使用して動的SQLを生成する必要があります。

SET @sql = NULL;

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'select id, ''',
      c.column_name,
      ''' as Word, ',
      c.column_name,
      ' as qty 
      from yt 
      where ',
      c.column_name,
      ' > 0'
    ) SEPARATOR ' UNION ALL '
  ) INTO @sql
FROM information_schema.columns c
where c.table_name = 'yt'
  and c.column_name not in ('id')
order by c.ordinal_position;

SET @sql 
  = CONCAT('select id, Word, qty
           from
           (', @sql, ') x  order by id');


PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SQL Fiddle with Demo を参照してください

23
Taryn

基本的に、データを列から行にピボット解除します。これには、UNIONALLを使用できます。フィルタは、ピボットされていないサブクエリ全体に適用することも、パーツに個別に適用することもできます。

select id, Word, Qty from
(
  select id, 'abc' Word, abc Qty from table1 
  union all
  select id, 'brt', brt from table1
  union all
  select id, 'ccc', ccc from table1
  union all
  select id, 'ddq', ddq from table1
  union all
  select id, 'eee', eee from table1
  union all
  select id, 'fff', fff from table1
  union all
  select id, 'gga', gga from table1
  union all
  select id, 'hxx', hxx from table1
) x
where Qty > 0
order by id;
7
RichardTheKiwi