Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to transpose a table in SQLite?

Hello so I have a table as such in SQlite:

   User    |  Group  |   Role    
John Smith |   A     |   admin
John Smith |   B     |   user
Jane Doe   |   A     |   user
Jane Doe   |   B     |   limit
Jane Doe   |   C     |   admin
Jack Brown |   A     |   admin, user

I want to transpose the table so there is only one user per row.The column headers are "Group". The values for "Group" would be values in the "Role" column from the first table.

So, it would look as such when transformed:

   User    |    A        |    B       |  C 
John Smith |   admin     |    user    |
Jane Doe   |   user      |    limit   | admin
Jack Brown |   admin,user|            |

How would one go about doing this SQLite?

like image 911
harcot Avatar asked Oct 24 '18 04:10

harcot


People also ask

How do I alter a table in SQLite?

Syntax. To rename a table, the SQLite ALTER TABLE syntax is: ALTER TABLE table_name RENAME TO new_table_name; table_name.

Can we transpose data in SQL?

A transposition is to rotate information from one row or column to another to change the data layout, for the purpose of making observations from a new perspective. Some transposition algorithms are simple, such as row to column, column to row and bidirectional transposition.

How do I change the primary key in SQLite?

In SQLite, you can not use the ALTER TABLE statement to drop a primary key. Instead, you must create a new table with the primary key removed and copy the data into this new table.


2 Answers

No need to use windowing functions since the "Group" column already provides the necessary value on which to transform. Not only does this simplify the query, but it also puts the values in the correct transformed column irregardless of the order or whether or not the "group" values are contiguous. (Also note that sqlite complains if group is used without delimiters since it is reserved keyword.)

SELECT User, 
       max(CASE WHEN "group" == 'A' THEN role END) as A,
       max(CASE WHEN "group" == 'B' THEN role END) as B,
       max(CASE WHEN "group" == 'C' THEN role END) as C
FROM SO52961250 t
GROUP BY User;
like image 76
C Perkins Avatar answered Sep 28 '22 04:09

C Perkins


The excellent solution offered by @CPerkins has the potential drawback of losing information. For example, consider what would happen if the data for "Jack Brown" was presented in two rows:

Jack Brown |   A     |   admin
Jack Brown |   A     |   user

To ensure no information is lost, one could use GROUP_CONCAT instead of MAX:

SELECT User, 
       GROUP_CONCAT(CASE WHEN "group" == 'A' THEN role END) as A,
       GROUP_CONCAT(CASE WHEN "group" == 'B' THEN role END) as B,
       GROUP_CONCAT(CASE WHEN "group" == 'C' THEN role END) as C
FROM SO52961250 t
GROUP BY User;
like image 41
peak Avatar answered Sep 28 '22 02:09

peak