Classic interview question in MySQL - row to column (column to row)

Table of contents

1 Introduction:  

1. Row to column (Pivot):

2. Unpivot:

2. The idea of ​​​​turning rows into columns and columns into rows

3. Realize

3.1. Realize row to column conversion

3.2. Summary of two methods to achieve (row to column) implementation  

3.3. Implementation (column to row) 

3.4. Summary (column to row)


1 Introduction:  

        In MySQL, row-to-column (Pivot) and column-to-row (Unpivot) are concepts used to change the layout of data tables. Row-to-column and column-to-row are techniques used under specific data conversion requirements, which can help change the way data is presented. , to accommodate different analysis and reporting requirements. The specific implementation method will vary depending on the actual needs and the specific circumstances of the query.

1. Row to column (Pivot):

        Row to column conversion refers to converting rows in the original data table into columns. This operation is often used to use the value of a certain column as a new column name and fill in the corresponding value in the corresponding position. For example, convert a student's grades in different subjects from a portrait layout to a landscape layout.

2. Unpivot:

        Column to row conversion refers to converting columns in the original data table into rows. This operation is often used to convert the values ​​of multiple columns into one column and use the original column names as the new columns. For example, convert the grades of different subjects from a horizontal layout to a vertical layout.

2. The idea of ​​​​turning rows into columns and columns into rows

        Converting rows to columns: First of all, for very scattered data, if we want to convert rows into columns, we need to have the idea of ​​​​sum. This is especially true for the group aggregation of aggregate functions in our MySQL learning process. important, so in the process of converting rows to columns, the aggregate function and group by group column are the most important. This can be achieved by using aggregate functions and conditional statements (such as `CASE WHEN`). The specific implementation method varies depending on the query requirements. Generally, `GROUP BY` is used for grouping and aggregation.

        Column to row: So how do we dismantle aggregated data, and what operations should we perform after dismantling it? This requires us to aggregate the disjointed data, that is, use our UNION ALL. Combines the results of multiple queries and adds a new column to the results that represents the original column name. Each query selects a subset, representing an original column.

3. Realize

3.1. Realize row to column conversion

/*-------------------------- MySQL中的行转列和列转行 ---------------------------------
-- MySQL中的行转列
-- 对于我们的stu_score这张表,我们的数据展示是以行为主,同一个人物的信息被拆分为多个行,行转列的思想就是想把多行转换为一行数据
  MySQL中的行转列和列转行
          张三          语文          78
          张三          数学          87
          张三          英语          65
          李四          语文          88
          李四          数学          90
          李四          英语          98
          王五          语文          73
          王五          数学          88
          王五          英语          90
其目的就是将我们的数据展示为:
          name      语文          数学           英语
          张三       78            87            65
          李四       88            90            98
          王五       73            88            90

  假想:伪列,上诉中的表每行都存在着我们的人物姓名,学科名称,即一课学科的信息,现在我们把所有的每一行都看作是包含语文、数学、英语的
          张三          语文          78          null (数学)           null (英语)
          张三          数学          87          null (语文)           null (英语)
          张三          英语          65
          李四          语文          88
          李四          数学          90
          李四          英语          98
          王五          语文          73
          王五          数学          88
          王五          英语          90
  行转列的解题步骤:
    1、确定分组列,转换列,数据列---确定数据中哪一个作为分组列(找同名字段),哪一个作为转换列,哪一个作为数据列
    2、生成伪列---声明伪列,即保证结构的完整性
    3、做分组查询---为第四步做铺垫,分组查询通常跟我们的聚合函数一起使用
    4、选择合适的聚合函数---使用聚合函数,把结构中的数据正确的计算出来

 */

1) Determine our grouping column and scan the entire table. Only our name has not changed, so the name serves as our grouping column. Secondly, we convert the columns. We need to convert the corresponding subject scores into columns. In turn, the score information becomes our data column

2) Generate pseudo columns

-- 生成伪列

select name,
       case subject when '语文' then score else null end as 'chinese',
       case subject when '数学' then score else null end as 'math',
       case subject when '英语' then score else null end as 'english'
from stu_score;

  result:

3) Make sure our grouping column is name

4) Because our grouping statements are usually used with our aggregate functions

-- 通过聚合函数和分组语句:

select name,max(chinese) as '语文成绩',max(math) as '数学成绩',max(english) as '英语成绩'
from (select name,
       case subject when '语文' then score else null end as 'chinese',
       case subject when '数学' then score else null end as 'math',
       case subject when '英语' then score else null end as 'english'
from stu_score) temp
group by name;

result:

 

3.2. Summary of two methods to achieve (row to column) implementation  

两步法:
公式:
select 分组列,
      聚合函数(m1)as 列名1,
      聚合函数(m2)as 列名2,
      聚合函数(m3)as 列名3,
from (select *,
    case 转换列 when 转换列值1 then 数据列 else .... end as m1,    
    case 转换列 when 转换列值2 then 数据列 else .... end as m2,
    case 转换列 when 转换列值3 then 数据列 else .... end as m3
    from 表名)临时表名
group by 分组列;



一步法:
公式:
select 分组列,
    聚合函数(case 转换列 when 转换列值1 then 数据列 else .... end) as 列名1,    
    聚合函数(case 转换列 when 转换列值2 then 数据列 else .... end) as 列名2,
    聚合函数(case 转换列 when 转换列值3 then 数据列 else .... end) as 列名3
    ...
from 表名
group by 分组列;

3.3. Implementation (column to row) 

  Create data table:

-- 将上面的行转列的查询结果存储为学生信息的表

create table stu_score_row_columns as (
    select name,
    max(case subject when '语文' then score else null end) as '语文',
    max(case subject when '数学' then score else null end) as '数学',
    max(case subject when '英语' then score else null end) as '英语'
from stu_score group by name
);
/*
数据展示:
    name 语文 数学 英语
    张三  78  87  65
    李四  88  90  98
    王五  73  88  90

列转行之后:思想:先转换我们第一行的数据,然后一层一层拼接使用union all来操作
    张三          语文          78
    张三          数学          87
    张三          英语          65
分析:
    1、表中的张三是通过表中的name所得到,语文作为我们的表头,可以通过'列名'获取,列所对应的值通过列名直接指定
 */

   result:

   Realize column transfer

 -- 先获取一行的数据,其中,subject列的值始终为字符串'语文',score列的值将与stu_score_row_columns表中的语文列的值相对应。

select name,'语文' as subject,语文 as 'score' from stu_score_row_columns
union all
select name,'数学' as subject,数学 as 'score' from stu_score_row_columns
union all
select name,'英语' as subject,英语 as 'score' from stu_score_row_columns
order by name;

  result:

3.4. Summary (column to row)

Summary: Implement column conversion method.
Problem-solving steps:
    1. Determine conversion columns and non-conversion columns.
    2. Generate new columns
    . 3. Use union or union all to merge.
    4. Perform order by sorting operation as needed.

Formula:
select non-conversion column, 'conversion column 1' as new conversion column name, conversion column 1 as new data column name from table name union all select non-conversion column
,
'conversion column 2' as new conversion column name, conversion column 2 as new data column name from table name
union all
select non-conversion column, 'conversion column 3' as new conversion column name, conversion column 3 as new data column name from table name  
order by ....;s

Notice:

        The new conversion column names and the new data column names must be consistent.

4. Hands-on practice

Row to column (Pivot) topic:
1. Given an order table, including three fields: order number (order_number), product name (product_name) and sales quantity (quantity), pivot the rows of the table to use the order number as the column name, and the sales quantity corresponding to each product name is used as the corresponding value.

Create a table and insert data:

 create table order_tab(
     order_number int comment '订单号',
     product_name varchar(40) comment '产品名称',
     quantity int comment '销售数量'
 ) COMMENT '订单表';

insert into order_tab(order_number, product_name, quantity) values (1,'球鞋',3),
                                                                   (1,'羽毛球',3),
                                                                   (3,'羽毛球',2),
                                                                   (2,'球鞋',6),
                                                                   (4,'矿泉水',3),
                                                                   (2,'苏打水',1),
                                                                   (2,'矿泉水',4);
-- 确定我们的行转列
select order_number '订单编号',
       sum(case when product_name = '球鞋' then quantity else 0 end) as '球鞋',
       sum(case when product_name = '羽毛球' then quantity else 0 end) as '羽毛球',
       sum(case when product_name = '矿泉水' then quantity else 0 end) as '矿泉水',
       sum(case when product_name = '苏打水' then quantity else 0 end) as '苏打水'
from order_tab group by order_number order by order_number;

  result:

Column transfer (Unpivot) topic:
1. Suppose there is a sales data table containing two fields: year (year), product A sales volume (product_a_sales) and product B sales volume (product_b_sales). Unpivot the table columns to The year is a column, and each product and corresponding sales volume are listed.
2. Given a market survey data table, including two fields: city name (city_name), demand for product A (product_a_demand) and demand for product B (product_b_demand), change the columns of the table to use city name as one column. And list each product and its corresponding demand.

  Solution 2:

  data preparation:

-- 实现列转行(数据准备)
create table market_servey(
    city_name varchar(30) comment '城市名称',
    product_a_demand int comment '产品A的需求量',
    product_b_demand int comment '产品B的需求量'
);

insert into market_servey(city_name, product_a_demand, product_b_demand) values ('贵阳',20,30),
                                                                                ('毕节',30,10),
                                                                                ('遵义',15,50),
                                                                                ('铜仁',60,10),
                                                                                ('黔东南',10,16);

 

  Code:

-- 实现列转行(列转行使用到union all)

select city_name,'product_a_demand' as '产品名称',product_a_demand as '产品数量' from market_servey
union all
select city_name,'product_b_demand' as '产品名称',product_b_demand as '产品数量' from market_servey
order by city_name;

  result:

Guess you like

Origin blog.csdn.net/qq_57492774/article/details/131690974