Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Dynamische Abfrage in MySQL

Um das gewünschte Ergebnis zu erhalten, müssen Sie beide unpivotieren die aktuellen Daten aus Spalten in Zeilen und drehen Sie dann das year Daten von Zeilen in Spalten.

MySQL hat keine PIVOT- oder UNPIVOT-Funktion, daher müssen Sie ein UNION ALL verwenden Abfrage zum Entpivotieren und eine Aggregatfunktion mit einem CASE zu schwenkender Ausdruck.

Wenn Sie über eine bekannte Anzahl von Werten verfügen, können Sie Werte ähnlich wie diese fest codieren:

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;

Siehe SQL Fiddle mit Demo .

Wenn Sie jedoch eine unbekannte Anzahl von Werten haben, müssen Sie eine vorbereitete Anweisung verwenden, um dynamisches SQL zu generieren. Der Code ähnelt dem Folgenden:

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;

Siehe SQL-Geige mit Demo . Das Ergebnis für beide Abfragen ist:

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