当前位置:网站首页>Row to column and column to row in MySQL

Row to column and column to row in MySQL

2022-06-27 18:46:00 Ink Sky Wheel


WeChat search “coder-home” Or scan the QR code below , Official account ,

Learn more about dry goods sharing at the first time , There are also various video tutorial resources . Scan it , Take me




  • The concept of row to column and column to row

    • What is row to column

    • What is column to row

  • Row to column experiment example

    • Example 1 : Using aggregate functions

    • Example 2 : Use group_concat function

    • Example 3 : Usage dynamics SQL Sentence block

  • Column to row experiment example

    • Example 1 : Use union all function

    • Example 2 : Use substring_index function

  • The final summary


The concept of row to column and column to row

Here, we need to reiterate the difference between column to row and column to column . There are many posts that are not strictly differentiated in their introduction , Naming describes how to convert a column to a row , But the title of the post does say row to column . From beginning to end, I haven't mentioned the matter of changing rows . therefore , I think it is necessary to make a distinction and understanding here .


What is row to column

The so-called row column conversion means that the data table has the same key Multiple lines of values value data , Convert to using a key Value , Make every row of data , One key Corresponding multiple value.

After row column conversion , The visual effect is : The total number of rows in the table has decreased , But the number of columns has increased .

The conversion process shown below is a simple process of row to column :




What is column to row

The so-called column to row conversion means that the same key Value corresponds to multiple value Column , Convert to multiline data , Make every row of data , To ensure a key Only one value.

After column to row conversion , The visual effect is : The number of columns in the table is reduced , But the number of lines has increased .

The conversion process shown below is a simple column to row process :




Row to column experiment example

Before the experiment , We need to prepare our experimental environment first , Prepare the table and the initialization data in the table .

  • Prepare to initialize the table structure

    CREATE TABLE `student_x` (
    `id` int(11) DEFAULT NULL,
    `name` varchar(255) DEFAULT NULL,
    `class` varchar(255) DEFAULT NULL,
    `score` int(255) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • Prepare to initialize the data in the table

    INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (1, ' Zhang San ', ' mathematics ', 78);
    INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (2, ' Zhang San ', ' English ', 93);
    INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (3, ' Zhang San ', ' Chinese language and literature ', 65);
    INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (4, ' Li Si ', ' mathematics ', 87);
    INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (5, ' Li Si ', ' English ', 90);
    INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (6, ' Li Si ', ' Chinese language and literature ', 76);
    INSERT INTO `student_x`(`id`, `name`, `class`, `score`) VALUES (7, ' Li Si ', ' history ', 69);
  • The experimental environment for row column conversion is as follows :



Example 1 : Using aggregate functions

We are in this example , Using aggregate functions sum、max、min、avg
To fulfill our row to column requirements , The specific experiments are as follows .

  • The following is the effect diagram of row to column conversion :


  • Use case when
    Statement to assemble new data columns

    select name,
    case when class = ' mathematics ' then score else null end as math_score,
    case when class = ' English ' then score else null end as engilsh_score,
    case when class = ' Chinese language and literature ' then score else null end as chinese_score,
    case when class = ' history ' then score else null end as history_score
    from student_x;


  • Based on the above rendering , We need to put the data results , according to name Column , Let the data rows with the same name be merged into the same row to display , meanwhile , Accounts in each column , There is only one row of data that has achievements , All the other lines are empty null, So they are used together max function , You can merge rows , And the subject score of each column will not affect the final subject score because of the consolidation of rows . To realize the above transformation SQL The statement is as follows :

    select name,
    max(case when class = ' mathematics ' then score else null end) as math_score,
    max(case when class = ' English ' then score else null end) as engilsh_score,
    max(case when class = ' Chinese language and literature ' then score else null end) as chinese_score,
    max(case when class = ' history ' then score else null end) as history_score
    from student_x
    group by name;

  

  • We use... On it case when
    Sentence to judge , Actually if
    Statements can also achieve case when
    The effect of the statement . Here's how to use if
    Result of statement :

    select name,
    max(if(class = ' mathematics ', score, null)) as math_score,
    max(if(class = ' English ', score, null)) as engilsh_score,
    max(if(class = ' Chinese language and literature ', score, null)) as chinese_score,
    max(if(class = ' history ', score, null)) as history_score
    from student_x
    group by name;

  • Implementation process analysis

    1. Here we use the aggregate function max, Take each student's name as key, Group statistics .

    2. Because each student has only one record for each subject , So we use aggregate functions sum The result of each subject after statistics , It is still a separate grade in this subject .

    3. If each student here has multiple score records for each subject , Aggregate functions cannot be used here max 了 , If you use max, The final result will be the maximum score of each student in each subject .

    4. The reason why we use max The purpose of is to achieve a grouping effect . there max have access to sum、min、avg Wait for the aggregate function to replace , Their three effects are similar to sum The effect of the function is the same here .

summary : The above implementation method , So that people often use , It is also the most familiar way . But there is a problem with this way of writing , When our subject name changes or increases or decreases , We SQL The statement also needs to be modified accordingly . Because we are SQL Statement has been used hard code
Hard code the name of the subject , So this is SQL Not very flexible .

We can refer to the following ways , Each one is slightly different , But these methods can basically meet our needs .


Example 2 : Use group_concat function

The aggregate function used above is implemented in a way similar to hard coding , To avoid hard coding , We can use gourp_concat
Function to implement , However, the effect that this function can achieve is slightly different from that achieved by using aggregate functions , The difference is that the converted columns are displayed differently . See the following effects for details .

  1. The effect picture we want to achieve is as follows :

  2. To achieve the above effect , We use group_concat Function can be directly completed ,SQL The statement is as follows :

    select name,
    group_concat(score separator ',') as 'scores'
    from student_x
    group by name;

  3. We can find that the converted columns above are merged and displayed in one column , We may not know which subject each comma separated grade represents . So we need to add the name of the displayed account in the converted column , Achieve the following effect :

  4. Achieve the effect shown in the above figure SQL The statement is as follows :

    select name,
    group_concat(class separator ',') as classes,
    group_concat(score separator ',') as scores
    from student_x
    group by name;

  5. In addition, we can put the subject name and subject score together , Then, it displays... Separated by commas , In this way, we can more clearly see the corresponding score of each subject . Achieve the effect shown in the figure below :

  6. As follows SQL The effect shown in the above picture can be satisfied :

    select name,
    group_concat(class,':',score separator ',') as 'class:score'
    from student_x
    group by name;

summary : Use group_concat
The effect that function can achieve , Compared to using aggregate functions , It doesn't need to be modified due to the change of account SQL sentence , So it may be more flexible . meanwhile , It also has its own shortcomings . That's how its columns are presented compared to using aggregate functions , Cannot be shown separately , It can only be connected with the specified separator and displayed in a column .

Of course, if we need to use separate columns to show the grades of each subject after conversion , We are based on group_concat The result of function conversion , combining substring
Function or substring_index
Function to intercept and split the result column to achieve the effect of dividing a column into multiple columns . But the effect is a little hard code
Function , Because when you intercept a string , You need to specify where to start intercepting , Where to intercept , How many elements to intercept .


Example 3 : Usage dynamics SQL Sentence block

Actually , Before we want to make a “ Transfer line column ” In the process of , The real difficulty is that we don't know how many subjects each student has taken , And I don't know what these subjects are , This leads us not to know our select Which fields do the following fields need to be written .

If we can put select name,[colums] from student_x group by name;
Statement columns
To precisely locate which fields , So our SQL And we're done 90%
. So next we need to dynamically assemble our columns Field contents .

Dynamic assembly SQL The procedure of the statement is as follows :

  1. We want to achieve the following effect of row column conversion :


  2. First make sure , What are all the subjects that students choose , We use distinct Statement to get the result set .

    select distinct class from student_x;

  3. in other words , All the students , The courses they choose are nothing more than the above 4 One or more of the courses in . We are select hinder columns Field , Most of the time , That is, to assemble this 4 A course . For students who do not have a choice of one of these courses , His corresponding grade of the course that has not been selected is blank null perhaps 0.

  4. So let's use dynamic assembly columns The result of SQL The statement is as follows :

    set @select_columns = ''; --  Defining variables 
    select
    @select_columns := concat(@select_columns,'sum(if(class= \'',class,'\',score,null)) as ',class, ',') as select_column -- When you assign , Use concat Function to connect the last set of fields
    from (
    select distinct class from student_x -- Count the set of account names after de duplication
    ) as t; -- Assign values to variables


    select @select_columns; --  View variable results 

  5. Assemble the last complete row to column SQL sentence ,SQL And the results are as follows :

    set @select_sql := concat('select name, ', 
    substring(@select_columns, 1, char_length(@select_columns) - 1),
    ' from student_x group by name;'
    ); -- Use concat function , assemble SQL sentence
    select @select_sql; -- See the final assembled complete SQL sentence


  6. Finally, execute SQL The statement is as follows :

    --  Prepare to carry out SQL sentence 
    prepare stmt from @select_sql;
    execute stmt; -- perform SQL sentence
    deallocate prepare stmt; -- Release variable resources


  7. Finally together SQL The statement is as follows :

    set @select_columns = ''; --  Defining variables 

    select
    @select_columns := concat(@select_columns,'sum(if(class= \'',
    class,'\',score,null)) as ',class, ',') as select_column -- When you assign , Use concat Function to connect the last set of fields
    from (
    select distinct class from student_x -- Count the set of account names after de duplication
    ) as t; -- Assign values to variables

    select @select_columns; -- View variable results

    set @select_sql := concat('select name, ',
    substring(@select_columns, 1, char_length(@select_columns) - 1),
    ' from student_x group by name;'
    ); -- Use concat function , assemble SQL sentence

    select @select_sql; -- See the final assembled complete SQL sentence

    -- Prepare to carry out SQL sentence
    prepare stmt from @select_sql;
    execute stmt; -- perform SQL sentence
    deallocate prepare stmt; -- Release variable resources


summary : The above dynamic assembly SQL The statement method avoids the SQL Statement needs to be rewritten , You can dynamically generate the name and number of accounts to be queried . But it's a little complicated , Unlike before, we used aggregate functions max perhaps group_concat So simple and clear .


Example of column to row

Example 1 : Use union all function

Before the column to row experiment , We need to prepare our experimental environment first , Prepare the table and the initialization data in the table . The table structure and initialization data are as follows :

  • Prepare to initialize the table structure

    CREATE TABLE `student_y` (
    `id` int(11) DEFAULT NULL,
    `name` varchar(255) DEFAULT NULL,
    `math_score` bigint(255) DEFAULT NULL,
    `engilsh_score` bigint(255) DEFAULT NULL,
    `chinese_score` bigint(255) DEFAULT NULL,
    `history_score` bigint(255) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • Prepare to initialize the data in the table

    INSERT INTO `student_y`(`id`, `name`, `math_score`, `engilsh_score`, `chinese_score`, `history_score`) VALUES (1, ' Zhang San ', 78, 93, 65, NULL);
    INSERT INTO `student_y`(`id`, `name`, `math_score`, `engilsh_score`, `chinese_score`, `history_score`) VALUES (2, ' Li Si ', 87, 90, 76, 69);
  • The experimental environment for column to row conversion is finally as follows :


After the preparation of the experimental environment , Next we start using union all To realize the function of column to row conversion .

  1. The conversion effect of column to row we want to achieve is as follows :


  2. We can check the scores of all students in each subject separately , give the result as follows :

    select name, math_score as score from student_y;
    select name, engilsh_score as score from student_y;
    select name, chinese_score as score from student_y;
    select name, history_score as score from student_y;   

  3. Based on each of the above query results , Use the final result union all
    Keywords merged together , The effect is as follows :

    select name, math_score as score from student_y
    union all
    select name, engilsh_score as score from student_y
    union all
    select name, chinese_score as score from student_y
    union all
    select name, history_score as score from student_y;

  4. here , We found that the requirements of converting columns to rows have been roughly realized in the results . But the order did not meet the requirements , Everyone's grades in each subject should be next to , But at present, it is not next to . So we need to base on the above query results , Check on the first floor of the package , Add one more order by Statement in an outer query , We can get the order we want . As shown below :

    select * from (
    select name, math_score as score from student_y
    union all
    select name, engilsh_score as score from student_y
    union all
    select name, chinese_score as score from student_y
    union all
    select name, history_score as score from student_y
    ) as x order by name;


  5. At this time, the result is very close to our final desired result , But we found that , We can't distinguish the grades of each student from the grades of each subject , So we need to include subjects in the result set , That is, when we query , The column names corresponding to each grade should also be included in the query fields . So we have the following SQL

    select * from (
    select name, 'math_score' as class, math_score as score from student_y
    union all
    select name, 'engilsh_score' as class, engilsh_score as score from student_y
    union all
    select name, 'chinese_score' as class, chinese_score as score from student_y
    union all
    select name, 'history_score' as class, history_score as score from student_y
    ) as x order by name,class;


summary : Here we use union all The function of , Find out the scores of all students in each subject separately , Then continue to merge the result sets . Finally, we can achieve the desired effect of turning columns into rows . But we found that at this time SQL In the sentence , As before, when we perform row column conversion , The method of using aggregate function to realize row to column conversion is similar to , Used hard code Hard coding of , If the account name or number changes , our SQL Statements also need to be dynamically modified , This is the drawback of this approach . But the advantage is that it is easier to understand .


Example 2 : Use substring_index function

sometimes , Our column to row table , Not like the previous example 1 , All columns are separate . Sometimes it is such data content , Multiple fields are linked by a specific symbol .

  • Prepare the table structure for the experimental environment :

    CREATE TABLE `student_y2` (
    `id` int(11) DEFAULT NULL,
    `name` varchar(255) DEFAULT NULL,
    `scores` varchar(255) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • Data for initialization :

    INSERT INTO `student_y2`(`id`, `name`, `scores`) VALUES (1, ' Zhang San ', '78,93,65');
    INSERT INTO `student_y2`(`id`, `name`, `scores`) VALUES (2, ' Li Si ', '87,90,76,69');
  • The final environment is as follows :


When the environment is ready , We started with a table like this , To convert columns to rows .

  1. Use substring_index(str, delim, count)
    Function to split fields , It needs to be understood here substring_index()
    Function functions .

    Based on the function explained above , We can get the following results :

    select 
    x.name,
    x.scores,
    char_length(x.scores) as length_scores,
    char_length(replace(x.scores, ',', '')) as length_scores_with_out_comma,
    char_length(x.scores) - char_length(replace(x.scores, ',', '')) + 1 as colum_num,
    substring_index(x.scores, ',', 1) as score1,
    substring_index(x.scores, ',', 2) as score12,
    substring_index(x.scores, ',', 3) as score123,
    substring_index(x.scores, ',', 4) as score1234,
    substring_index(substring_index(x.scores, ',', 1), ',', -1) as colum1,
    substring_index(substring_index(x.scores, ',', 2), ',', -1) as colum2,
    substring_index(substring_index(x.scores, ',', 3), ',', -1) as colum3,
    substring_index(substring_index(x.scores, ',', 4), ',', -1) as colum4
    from student_y2 as x;


    1. If count Positive number , So it's counting from left to right , The first N All of the contents to the left of the separator ;

    2. contrary , If it's a negative number , So it's counting from the right , The first N Everything to the right of the separator ;

    3. If you want to get a string in the middle of a string , Then get all of the left first , Then, based on the intercepted string, you can get all the strings on the right to get the desired string .

  2. As can be seen from the above results , We can use substring_index Function to intercept from the original table score Value , Intercept according to commas . The key to the problem is that we need to use a sequence to dynamically determine where to solve the problem . and MySQL There happens to be a system table in mysql.help_topic
    , This table can provide the sequence we need 0,1,2,3,4,5,6...n
    . Based on this table , We can build the following SQL And result :

    select * from mysql.help_topic y;


    select 
    x.name,
    substring_index(substring_index(x.scores, ',', y.help_topic_id + 1), ',', -1) as 'score'
    from student_y2 as x
    join mysql.help_topic y
    on y.help_topic_id < (length(x.scores) - length(replace(x.scores, ',', '')) + 1);


  3. Now we use mysql.help_topic
    Primary key value of the table help_topic_id
    Value , The less than relation is used in association , This will cycle through and judge the data in the table every time , Know that the condition of association is not satisfied , This technique is very clever . If we don't use mysql.help_topic
    , We create a table with rows and columns by ourselves , The data in the table is from 0,1,2,3,4,5,6...n
    Self increasing data , The same effect can be achieved .

summary : We used substring_index
Function with a sequence table mysql.help_topic
To complete the function of dynamically converting columns to rows . This method does not cause... Because the data in the column increases or decreases SQL Need to re , It has good universality , It can meet most of the needs of column to row transfer . But its disadvantage is that it is not easy to understand ,SQL The sentence is quite skillful . In addition, special format requirements are also required for the input original row data , The requirement is to use a specific symbolic link string as a column of data to appear in the original input data .


The final summary

At the beginning of the article , First, the concept of row and column transferring to each other is briefly clarified , Because many people confuse row to column and column to row . The most obvious distinction between row to column and column to row is as follows :

  • Transfer line column , There are fewer lines in the final result , There are more columns .

  • Column turned , There are fewer columns in the final result , More lines .

Then , We have conducted experimental demonstrations for row to column and column to row respectively .

In the experiment of row to column , We used three ways to demonstrate .

  1. Using aggregate functions max To realize the requirement of row column conversion .

    1. advantage : Easy to understand , It is also the way that people often or first think of .

    2. shortcoming : If key Value changes corresponding to SQL The statement needs to be adjusted accordingly .

  2. Use group_concat To realize the requirement of row column conversion .

    1. advantage :key A change in value does not result in SQL Rewriting of .

    2. shortcoming : Results after row column conversion , Columns are not displayed separately , It is shown from a string that is connected together at some symbolic interval .

  3. Use dynamic assembly SQL Statement block to realize the requirement of row to column conversion .

    1. advantage :key A change in value does not result in SQL Rewriting of , Display and use of columns at the same time max The demonstration results of aggregate functions are consistent .

    2. shortcoming :SQL The statement is divided into several steps , The process is a little complicated , It's not easy to understand .

In the column to row experiment , We used two ways to demonstrate .

  1. Use union all Function to realize the requirement of column to row conversion .

    1. advantage : Easy to understand , Such a way makes us think of the implementation way first .

    2. shortcoming :key A change in value will result in SQL Need to rewrite .

  2. Use substring_index Function combined with continuous auto increment sequence to complete the requirement of column to row conversion .

    1. advantage :key A change in value does not result in SQL Rewriting of .

    2. shortcoming : It's not easy to understand , There is a very clever SQL skill . There are special requirements for input columns , You need to use the specified characters to join together to form multiple columns of string as input .

Variant classification of row to column :

Variant classification of column to row :




WeChat search “coder-home” Or scan the QR code below , Official account ,

Learn more about dry goods sharing at the first time , There are also various video tutorial resources . Scan it , Take me



原网站

版权声明
本文为[Ink Sky Wheel]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/178/202206271615599421.html