mysql之常用函数,行转列等相关运用

一.相关常用函数的使用

提示:网上已经很多了,包括各个博主,官网资料等,此处不再赘述!
此处引用: mysql常用函数
此处引用资料: mysql常用函数解析
此处引用资料: mysql常用函数解析
此处参考资料: mysql行转列,列转行

大家可收集资料学习


二.多字段列转行:

1.先解读函数及思路

1.使用函数:

字符串函数:
CONCAT:字符串拼接,CONCAT(str1,str2,…)
GROUP_CONCAT(expr):该函数将非空列值按照分组条件进行合并并最终返回

row_number() over(partition by 分组列 order by 排序列 desc):分组排序功能

条件控制函数:CASE WHEN … THEN …ELSE… END
扩展:

IF(expr1,expr2,expr3):expr1为true,返回expr2,否则返回expr3。
IFNULL(expr1,expr2):如果expr1为null,就返回expr2,否则返回expr1。
NULLIF(expr1,expr2):如果expr1和expr2相等,就返回null 否则返回expr1。
CASE WHEN THEN ELSE END;

聚合函数:MAX(),SUM():此处运用要看具体行转列字段的数据类型,比如字符串,整数据,浮点数,金额等等

2.思路

分为两种情况:
1.直接将一些字段定死
2.动态拼接字段
使用的场景需要根据需求来,比如课程等,高中基本固定,大学会根据不同专业有不同的课程(就要使用动态的)

即将生成的动态字段包括条件分支等,使用字符串拼接起来,然后传入主SQL中作为查询的字段。
存储过程逻辑也是一样,将动态SQL进行组合查询而已。

2.SQL脚本准备

-- 创建示例数据表
CREATE TABLE teacher_assignments (
    teacher_name VARCHAR(50),
    org_name VARCHAR(50),
    position VARCHAR(50)
);

-- 插入示例数据
INSERT INTO teacher_assignments (teacher_name, org_name, position)
VALUES
    ('曹塽', '规划研究所', '副主任规划师'),
    ('曹塽', '信息中心', '应用工程师'),
    -- 其他数据行
    ('其他教师', '其他组织', '其他职位');
select * from teacher_assignments

在这里插入图片描述

3.方式一:存储过程

SET @sql = NULL;
SELECT
  GROUP_CONCAT(
    DISTINCT
    CONCAT(
     --rn 拼接到字段的org1,org2
      'MAX(CASE WHEN rn = ', rn, ' THEN org_name ELSE ''/'' END) AS org', rn, ',', 
      'MAX(CASE WHEN rn = ', rn, ' THEN position ELSE ''/'' END) AS position', rn
    )
  ) INTO @sql
FROM (
    SELECT DISTINCT 
           ROW_NUMBER() OVER(PARTITION BY teacher_name ORDER BY org_name) AS rn
    FROM teacher_assignments
) AS Ranks;

SET @sql = CONCAT('SELECT teacher_name, ', @sql, ' FROM (
    SELECT teacher_name, org_name, position,
           ROW_NUMBER() OVER(PARTITION BY teacher_name ORDER BY org_name) AS rn
    FROM teacher_assignments
) AS RankedData
GROUP BY teacher_name;');

-- 执行动态生成的SQL
PREPARE dynamic_sql FROM @sql;
EXECUTE dynamic_sql;
DEALLOCATE PREPARE dynamic_sql;

查询结果:
在这里插入图片描述

4.方式二:纯单查询SQL

1.先获取动态字段(字段名可根据需求自定义)

比如课程:MAX(CASE WHEN kcname= ', 名称具体字符串,ID,编码等, ’ THEN 名称END) AS 课程名称(根据需求调整)

-- 方式一		
SELECT
  GROUP_CONCAT(
    DISTINCT
    CONCAT(
      'MAX(CASE WHEN rn = ', rn, ' THEN org_name END) AS org', rn, ',',
      'MAX(CASE WHEN rn = ', rn, ' THEN position END) AS position', rn
    )
  ) 
FROM (
    SELECT DISTINCT 
           ROW_NUMBER() OVER(PARTITION BY teacher_name ORDER BY org_name) AS rn
    FROM teacher_assignments
) AS Ranks;

-- 方式二
SELECT
  GROUP_CONCAT(
    DISTINCT
    CONCAT(
      'MAX(IF(rn = ', rn, ',org_name,''-'')) AS org', rn, ',',
      'MAX(IF(rn = ', rn, ',position,''-'')) AS position', rn
    )
  ) 
FROM (
    SELECT DISTINCT 
           ROW_NUMBER() OVER(PARTITION BY teacher_name ORDER BY org_name) AS rn
    FROM teacher_assignments
) AS Ranks;

如图:
在这里插入图片描述

2.将1中的动态字段拼接字符串,放入到主SQL中(即在代码中查询2次,将第一次的结果作为参数,传入的SQL2中作为动态字段,后续更新至案例)

-- 方式一
SELECT 
    teacher_name,
    MAX(CASE WHEN rn = 1 THEN org_name ELSE '-' END) AS org1,-- 此场景可自定义具体的值
    MAX(CASE WHEN rn = 1 THEN position ELSE '-' END) AS position1,
    MAX(CASE WHEN rn = 2 THEN org_name ELSE '-' END) AS org2,
    MAX(CASE WHEN rn = 2 THEN position ELSE '-' END) AS position2
FROM (
    SELECT 
        teacher_name,
        org_name,
        position,
        ROW_NUMBER() OVER (PARTITION BY teacher_name ORDER BY org_name, position) AS rn
    FROM teacher_assignments
) AS assignments_pivoted
--WHERE teacher_name = '曹塽'
GROUP BY teacher_name;

-- 方式二
SELECT 
    teacher_name,
   MAX(IF(rn = 1,org_name,'')) AS org1,MAX(IF(rn = 1,position,'-')) AS position1,MAX(IF(rn = 2,org_name,'-')) AS org2,MAX(IF(rn = 2,position,'-')) AS position2
FROM (
    SELECT 
        teacher_name,
        org_name,
        position,
        ROW_NUMBER() OVER (PARTITION BY teacher_name ORDER BY org_name, position) AS rn
    FROM teacher_assignments
) AS assignments_pivoted
-- WHERE teacher_name = '曹塽'
GROUP BY teacher_name;

查询结果如图:
在这里插入图片描述


三.Mybatis Plus中以上两种方式的使用案例

注:如果是需要传入相关过滤条件,或者分页,直接在SQL中加语句就行(存储过程的参数传递自行修改)

1.存储过程的调用(直接在你对应的Mapper中加注解,或者用XML的方式也可以)

存储过程的使用带来的好坏,自行查阅

(此处和上文数据不符,只是演示案例,对应着来即可,改的是函数名字和具体的SQL语句罢了) 要体验过程,而不是直接copy,不要当CV侠!

	//p1() 为函数名称	
    @Select("{call p1()}")
    @Options(statementType = StatementType.CALLABLE)
    List<SomeData> getSomeData();

2.将动态SQL,传入到SQL(分2次查询)

注:我们不准使用存储过程,就用这种

    String dynamicSql = scoreManageMapper.getDynamicSQl();
    List<SomeData> data = scoreManageMapper.getListData(dynamicSql);
//1.动态字段字符串,XML配置
<select id="getDynamicSQl" resultType="java.lang.String">
        SELECT
            GROUP_CONCAT(DISTINCT
                         CONCAT(
                                 'MAX(CASE WHEN s.courseName = ''',
                                 c.id,
                                 ''' THEN s.score ELSE 0 END) AS ',
                                 REPLACE(c.name, ' ', '_')
                             ))
        from course_manage c
    </select>

//2.传入动态SQL参数,XML配置
<select id="getListData" resultType="com.example.localdemo.response.SomeData">
        select
            cm.className,
            sm.name as studentName,
            #{dynamicSql},  //传入的动态SQL
            SUM(s.score) totalScore,
            RANK() OVER (PARTITION BY cm.className ORDER BY SUM(s.score)) DESC) AS classRank //班级排名
        FROM score_manage s
                 left join student_manage sm on sm.id = s. studentName
                 left join class_manage cm on cm.id = s.onClass
        GROUP BY sm.id,cm.id
    </select>

四.扩展

在SQLServer中使用类似(语法,或者有些函数使用不同)

如报表需求:我需要知道某个人,在某年中的人事调动(包括公司,部门,岗位等变动),以及工作天数,请假天数,人员编码,名称,年总天数,人数【公式占比计算】等 字段

注:额外场景补充


五.总结

吃了没文化的亏,不就得恶补学习么!

如有不同的见解、看法或者有疑问的地方,欢迎留言共同学习!

Day Day No Bug !


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值