sql >> Databáze >  >> RDS >> Mysql

problém s kontingenční tabulkou mysql

Když se pokoušíte pivotovat dynamickou nebo neznámou hodnotu, vždy bych vám doporučil, abyste nejprve začali se statickou nebo pevně zakódovanou verzí dotazu a poté ji převedli na dynamické SQL.

MySQL nemá funkci PIVOT, takže k získání výsledku budete muset použít agregační funkci s výrazem CASE. Statická verze kódu bude podobná následující:

select t.id teamid, 
  t.name teamname, 
  p.id processid, 
  p.name processname,
  max(case when pd.keyname = 'shape' then tpd.value end) shape,
  max(case when pd.keyname = 'vegetable' then tpd.value end) vegetable,
  max(case when pd.keyname = 'fruit' then tpd.value end) fruit,
  max(case when pd.keyname = 'animal' then tpd.value end) animal
from teams t
inner join teamprocesses tp
  on t.id = tp.teamid
inner join TeamProcessDetails tpd
  on tp.id = tpd.teamProcessId
inner join processes p
  on tp.processid = p.id
inner join processdetails pd
  on p.id = pd.processid
  and tpd.processDetailsid = pd.id
group by t.id, t.name, p.id, p.name;

Viz SQL Fiddle s ukázkou .

Nyní, pokud budete mít neznámý počet keynames které chcete převést na sloupce, pak budete muset použít připravené prohlášení pro generování dynamického SQL. Kód bude podobný:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when pd.keyname = ''',
      keyname,
      ''' then tpd.value end) AS ',
      replace(keyname, ' ', '')
    )
  ) INTO @sql
from ProcessDetails;

SET @sql 
    = CONCAT('SELECT t.id teamid, 
                t.name teamname, 
                p.id processid, 
                p.name processname, ', @sql, ' 
              from teams t
              inner join teamprocesses tp
                on t.id = tp.teamid
              inner join TeamProcessDetails tpd
                on tp.id = tpd.teamProcessId
              inner join processes p
                on tp.processid = p.id
              inner join processdetails pd
                on p.id = pd.processid
                and tpd.processDetailsid = pd.id
              group by t.id, t.name, p.id, p.name;');

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

Viz SQL Fiddle s ukázkou .

Jedna věc, kterou je třeba mít na paměti GROUP_CONCAT funkce pro vytvoření řetězce sloupců má výchozí maximální délku 1024, takže pokud budete mít v tomto řetězci mnoho znaků, možná budete muset změnit hodnotu relace pro group_concat_max_len .

Tento dotaz poskytne výsledek:

| TEAMID | TEAMNAME | PROCESSID | PROCESSNAME |  SHAPE | VEGETABLE |  FRUIT | ANIMAL |
|      1 |    teamA |         1 |    processA | circle |    carrot |  apple | (null) |
|      1 |    teamA |         2 |    processB | (null) |    (null) | (null) |    dog |



  1. Storage Engine Volba:Aria

  2. Jsou tyto znaky platné pro XML?

  3. MySQL Group od SUM

  4. SQLAlchemy nutí in_() používat literály