Mysql
 sql >> Base de données >  >> RDS >> Mysql

Requête dynamique dans MySQL

Afin d'obtenir le résultat souhaité, vous devrez à la fois dépivoter les données actuelles des colonnes en lignes, puis faites pivoter l'year données des lignes dans les colonnes.

MySQL n'a pas de fonction PIVOT ou UNPIVOT, vous devrez donc utiliser un UNION ALL requête à unpivot et une fonction d'agrégation avec un CASE expression à faire pivoter.

Si vous avez un nombre connu de valeurs, vous pouvez coder en dur des valeurs similaires à ceci :

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;

Voir SQL Fiddle avec démo .

Mais si vous allez avoir un nombre inconnu de valeurs, vous devrez utiliser une instruction préparée pour générer du SQL dynamique. Le code ressemblera à ce qui suit :

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;

Voir SQL Fiddle avec démo . Le résultat pour les deux requêtes est :

| LOCID | EVENT | 2011 | 2012 |
-------------------------------
|     1 |   Abc |   10 |   20 |
|     1 | Birth |  100 |   98 |
|     1 | Death |   60 |   70 |