MySQL – Joining tables and turning specific rows into “virtual” columns

I am doing some database queries on WordPress. I am joining the usermeta table and users table.

the users table has a single row for each user.
the usermeta table has multiple rows for each user as the “meta_keys” (categories of meta data of each user) can contain all kind of information.

Read More

In a query I now would like to create a result set with only one row per user and with additional columns for selected meta_key values defined.

e.g. having an additional columns with the nickname – it should show the content of usermeta.meta_value when usermeta.meta_keys = ‘nickname’.

Here’s my current query with the unwanted duplication of rows

SELECT 
wusers.ID,
wusers.user_login, 
wusers.display_name,
wmeta.meta_key,
wmeta.meta_value,
wmeta.user_id   
FROM
  $wpdb->users wusers
  INNER JOIN $wpdb->usermeta wmeta ON wusers.ID = wmeta.user_id
WHERE 1 = 1
AND wmeta.meta_key = 'nickname'
OR wmeta.meta_key = 'description'
OR wmeta.meta_key = 'userphoto_thumb_file'

Is there any MySQL magic I can use to do this and turn data of certain the rows to new “virtual” columns?

Related posts

Leave a Reply

1 comment

  1. What you seek is commonly called a crosstab query:

    Select U.Id
        , Min( Case When M.meta_key = 'nickname' Then M.meta_value End ) As nickname
        , Min( Case When M.meta_key = 'description' Then M.meta_value End ) As description
        , Min( Case When M.meta_key = 'userphoto_thumb_file' Then M.meta_value End ) As userphoto_thumb_file
    From users As U
        Join usermeta As M
            On M.user_id = U.id
    Group By U.id
    

    It should be noted that you can only do this with static SQL and static columns. The SQL langugage itself was not really designed for dynamic column generation. To dynamically assemble the columns, you will need to dynamically assemble the query (aka dynamic SQL) in your middle-tier code.