SQL – Como transpor?

Eu tenho algo semelhante à seguinte tabela:

================================================ | Id | UserId | FieldName | FieldValue | =====+========+===============+================| | 1 | 100 | Username | John Doe | |----+--------+---------------+----------------| | 2 | 100 | Password | pass123! | |----+--------+---------------+----------------| | 3 | 102 | Username | Jane | |----+--------+---------------+----------------| | 4 | 102 | Password | $ecret | |----+--------+---------------+----------------| | 5 | 102 | Email Address | jane@email.com | ------------------------------------------------ 

Eu preciso de uma consulta que me dê um resultado como este:

 ================================================== | UserId | Username | Password | Email Address | =========+===========+===========================| | 100 | John Doe | pass123! | | |--------+-----------+----------+----------------| | 102 | Jane | $ecret | jane@email.com | |--------+-----------+----------+----------------| 

Observe que os valores em FieldName não estão limitados a nome de usuário, senha e endereço de email. Eles podem ser qualquer coisa como são definidos pelo usuário.

Existe uma maneira de fazer isso no SQL?

O MySQL não suporta a syntax ANSI PIVOT / UNPIVOT, de modo que você use:

  SELECT t.userid MAX(CASE WHEN t.fieldname = 'Username' THEN t.fieldvalue ELSE NULL END) AS Username, MAX(CASE WHEN t.fieldname = 'Password' THEN t.fieldvalue ELSE NULL END) AS Password, MAX(CASE WHEN t.fieldname = 'Email Address' THEN t.fieldvalue ELSE NULL END) AS Email FROM TABLE t GROUP BY t.userid 

Como você pode ver, as instruções CASE precisam ser definidas por valor. Para tornar essa dinâmica, você precisaria usar a syntax Prepared Statement (dynamic SQL) do MySQL .

Você poderia usar GROUP_CONCAT

(não testado)

 SELECT UserId, GROUP_CONCAT( if( fieldname = 'Username', fieldvalue, NULL ) ) AS 'Username', GROUP_CONCAT( if( fieldname = 'Password', fieldvalue, NULL ) ) AS 'Password', GROUP_CONCAT( if( fieldname = 'Email Address', fieldvalue, NULL ) ) AS 'Email Address', FROM table GROUP BY UserId