Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mysql select dynamic row values as column names, another column as value

I have a legacy table of user information (that is still in active use) and I cannot change the structure of -

id    name       value ------------------------------ 0     timezone   Europe/London 0     language   en 0     country    45 0     something  x 1     timezone   Europe/Paris 1     language   fr 1     country    46 

timezone/language/country etc are only examples of names, they can be variable/there is no finite list other than unique on rows of that column

I need a MySQL compatible SQL query that would return -

id    timezone       language    country  something --------------------------------------------------- 0     Europe/London  en          45       x 1     Europe/Paris   fr          46 

I've looked through various answers on stackoverflow around hacking Pivot table functionality in to MySQL, and similar but none of them seem to match this case of using variable column name alias from unique row values from a column of the same table. Although I have had little sleep so they're all starting to become a bit of a blur, apologies in advance.

Closest I could find would be to use prepared statements https://stackoverflow.com/a/986088/830171 which would first get all possible/unique values from name column and build a query that uses CASE WHEN, and/or multiple sub-SELECT or JOIN on same table queries.

The alternatives I can think of would be to get all rows for that user id and process them in the application itself in a for-loop, or attempt to limit the names to a finite amount and use sub-SELECTs/JOINs. However that second option is not ideal if a new name is added I'd have to revisit this query.

Please tell me I've missed something obvious

like image 952
gingerCodeNinja Avatar asked Jun 07 '12 03:06

gingerCodeNinja


People also ask

HOW CAN GET row values as column names in MySQL?

SET @sql = CONCAT('SELECT Meeting_id, ', @sql, ' FROM Meeting WHERE <condition> GROUP BY Meeting_id'); Similarly, you can also apply JOINS in your SQL query while you display row values as columns in MySQL. After you convert row to column in MySQL, you can use a charting tool to plot the result in a table.

How do I get column names dynamically in SQL?

Solution 1. The only way to do that is use build your command into a string, and use EXEC to run the result: table and column name parsing is conducted early in the SQL command execution process and have been replaced before any of the actual query is executed.

What is dynamic column in MySQL?

Dynamic columns is a feature that allows one to store different sets of columns for each row in a table. It works by storing a set of columns in a blob and having a small set of functions to manipulate it.

How do I select different columns in MySQL?

To select multiple columns from a table, simply separate the column names with commas! For example, this query selects two columns, name and birthdate , from the people table: SELECT name, birthdate FROM people; Sometimes, you may want to select all columns from a table.


1 Answers

Unlike some other RDBMS MySQL doesn't have native support for pivoting operations of this sort by design (the developers feel it's more suited to the presentation, rather than database, layer of your application).

If you absolutely must perfom such manipulations within MySQL, building a prepared statement is the way to go—although rather than messing around with CASE, I'd probably just use MySQL's GROUP_CONCAT() function:

SELECT CONCAT(   'SELECT `table`.id', GROUP_CONCAT('      ,    `t_', REPLACE(name, '`', '``'), '`.value          AS `', REPLACE(name, '`', '``'), '`'      SEPARATOR ''),  ' FROM `table` ', GROUP_CONCAT('      LEFT JOIN `table`   AS `t_', REPLACE(name, '`', '``'), '`             ON `table`.id = `t_', REPLACE(name, '`', '``'), '`.id            AND `t_', REPLACE(name, '`', '``'), '`.name = ', QUOTE(name)      SEPARATOR ''),  ' GROUP BY `table`.id' ) INTO @qry FROM (SELECT DISTINCT name FROM `table`) t;  PREPARE stmt FROM @qry; EXECUTE stmt; 

See it on sqlfiddle.

Note that the result of GROUP_CONCAT() is limited by the group_concat_max_len variable (default of 1024 bytes: unlikely to be relevant here unless you have some extremely long name values).

like image 170
eggyal Avatar answered Oct 08 '22 04:10

eggyal