web-dev-qa-db-ja.com

SQL-転置する方法?

次の表のようなものがあります。

================================================
| 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 | [email protected] |
------------------------------------------------

次のような結果が得られるクエリが必要です。

==================================================
| UserId | Username  | Password | Email Address  |
=========+===========+===========================|
| 100    | John Doe  | pass123! |                |
|--------+-----------+----------+----------------|
| 102    | Jane      | $ecret   | [email protected] |
|--------+-----------+----------+----------------|

FieldNameの値は、ユーザー名、パスワード、および電子メールアドレスに限定されないことに注意してください。ユーザー定義なので、何でもかまいません。

SQLでこれを行う方法はありますか?

21

MySQLはANSI PIVOT/UNPIVOT構文をサポートしていないため、次のように使用します。

  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

ご覧のとおり、CASEステートメントは値ごとに定義する必要があります。これを動的にするには、 MySQLの準備済みステートメント(動的SQL)構文 を使用する必要があります。

42
OMG Ponies

GROUP_CONCAT を使用できます

(未試験)

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
1
Sam Saffron