Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Consulta dinâmica no MySQL


Para obter o resultado desejado, você precisará unpivot os dados atuais das colunas em linhas e, em seguida, gire o year dados de linhas em colunas.

MySQL não tem uma função PIVOT ou UNPIVOT, então você precisará usar um UNION ALL query para unpivot e uma função agregada com um CASE expressão para pivotar.

Se você tiver um número conhecido de valores, poderá codificar valores semelhantes a este:
select locid,
  event,
  max(case when year = 2011 then value end) `2011`,
  max(case when year = 2012 then value end) `2012`
from
(
  select LocId, Year, 'Birth' event, Birth value
  from yt
  union all
  select LocId, Year, 'Death' event, Death value
  from yt
  union all
  select LocId, Year, 'Abc' event, Abc value
  from yt
) d
group by locid, event;

Consulte SQL Fiddle with Demo .

Mas se você tiver um número desconhecido de valores, precisará usar uma instrução preparada para gerar SQL dinâmico. O código será semelhante ao seguinte:
SET @sql = NULL;
SET @sqlUnpiv = NULL;
SET @sqlPiv = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'select locid, year, ''',
      c.column_name,
      ''' as event, ',
      c.column_name,
      ' as value 
      from yt '
    ) SEPARATOR ' UNION ALL '
  ) INTO @sqlUnpiv
FROM information_schema.columns c
where c.table_name = 'yt'
  and c.column_name not in ('LocId', 'Year')
order by c.ordinal_position;

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(CASE WHEN year = ',
      year,
      ' THEN value else null END) AS `',
      year, '`'
    )
  ) INTO @sqlPiv
FROM yt;

SET @sql 
  = CONCAT('SELECT locid,
              event, ', @sqlPiv, ' 
            from 
            ( ',  @sqlUnpiv, ' ) d
            group by locid, event');

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

Consulte SQL Fiddle with Demo . O resultado para ambas as consultas é:
| LOCID | EVENT | 2011 | 2012 |
-------------------------------
|     1 |   Abc |   10 |   20 |
|     1 | Birth |  100 |   98 |
|     1 | Death |   60 |   70 |