sql >> Database >  >> RDS >> Mysql

problemen met mysql draaitabel

Wanneer u dynamische of onbekende waarde probeert te draaien, raad ik u altijd aan eerst met een statische of hardgecodeerde versie van de query te beginnen en deze vervolgens naar dynamische SQL te converteren.

MySQL heeft geen PIVOT-functie, dus u moet een aggregatiefunctie met een CASE-expressie gebruiken om het resultaat te krijgen. De statische versie van de code ziet er ongeveer als volgt uit:

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;

Zie SQL Fiddle met demo .

Als u nu een onbekend aantal keynames krijgt, die u naar kolommen wilt converteren, moet u een voorbereide verklaring om dynamische SQL te genereren. De code zal lijken op:

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;

Zie SQL Fiddle met demo .

Een ding om in gedachten te houden is de GROUP_CONCAT functie om de reeks kolommen te maken heeft een standaard maximale lengte van 1024, dus als u veel tekens in deze reeks gaat hebben, moet u mogelijk de sessiewaarde voor de group_concat_max_len wijzigen .

Deze zoekopdracht geeft een resultaat:

| 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. MySQL from_unixtime na 2038-01-19?

  2. SQL/PHP:Toon top 3 meest verkochte producten uit database

  3. Een web-app maken vanaf nul met Python Flask en MySQL:deel 5

  4. Oracle-fout bij opstarten een andere opstart-/afsluitbewerking van deze instantie wordt uitgevoerd