首页 > 数据库 >mysql常用报表处理及数据迁移写法SQL

mysql常用报表处理及数据迁移写法SQL

时间:2023-10-20 16:06:36浏览次数:39  
标签:totalTime 10 SQL WHEN 60 mysql 写法 id SELECT


熟悉一些常用的sql写法便于工作中快速导出数据,本文不涉及到业务,所以对表库做了名字的修改,仅提供一些用法的说明。


以下直接举例子并讲解


1 单表批量数据迁移


场景:日志迁移
  
 
  

   具体实例:将test_log2日志表2的数据全部迁移到test_log1日志表1
  
 
  
sql:
 
  

   INSERT INTO `xxx`.test_log1
  
 
  

   (
  
 
  

       `operate_account_id`,
  
 
  

       `student_id`, `transfer_type`, `gmt_create`, `gmt_modify`
  
 
  

   )
  
 
  

   SELECT
  
 
  

       operate_account_id AS operate_account_id
  
 
  

       ,student_id AS student_id    
  
 
  

       ,1 AS transfer_type
  
 
  

       ,gmt_create AS gmt_create
  
 
  

       ,gmt_modify AS gmt_modify
  
 
  

   FROM `xxx`.test_log2;
  
 
  
说明:数据量只有几十万的话,还是很轻松的,可以直接使用上面sql


 



2 联表批量更新数据


场景:tab2表的数据
  
 
  

   具体实例:需要把tab2表的最新记录的insertTime更新到tab1的lastFollowTime
  
 
  

   sql:
  
 
  

   UPDATE `xxx`.tab1 t
  
 
  

       INNER JOIN (
  
 
  

           SELECT MAX(insertTime) AS insertTime,userId FROM `xx`.tab2
  
 
  

               WHERE type!=2 OR (type=2 and (content is not null and content != "" ))  GROUP BY userId
  
 
  

       ) f
  
 
  

       ON t.UserId = f.userId
  
 
  

       SET t.lastFollowTime = f.insertTime
  
 
  

       WHERE f.insertTime is not null
  
 
  

           AND (t.lastFollowTime IS NULL
  
 
  

               OR DATE_FORMAT(f.insertTime, '%Y-%m-%d %H:%i:%s') <  DATE_FORMAT(f.insertTime, '%Y-%m-%d %H:%i:%s')
  
 
  

           );
  
 
  

   说明:这里有两个小技巧
   - 第一个是left join子查询里面用分组+max找出当前userId最新的那条记录(算是一个找最新记录的小技巧)
  
 
  

   - 第二个是DATE_FORMAT(f.insertTime, '%Y-%m-%d %H:%i:%s')进行比较,因为`xx`.tab2的时间格式是这样的"2019-09-10 17:57:48.793",所以“2019-09-10 17:57:48.793”会永远大于“2019-09-10 17:57:48”,为了过滤这些条件,就加了个DATE_FORMAT





3 多次left join联表导出数据

场景:查出某个时间段带有某些字段的报表数据
 
  
具体实例:查出2019/0.9/01至2019/10/01之间的数据,以下会说明一些查的技巧
 
  
sql:
 
  

   SELECT
  
 
  

       # S点
  
 
  

       DATE_FORMAT(tc.start_date, "%Y/%m/%d %H:%i") AS "开始时间"
  
 
  

       ,DATE_FORMAT(date_add(tc.start_date, interval 1 hour), "%Y/%m/%d %H:%i") AS "结束时间"
  
 
  

       # A点
  
 
  

       ,dep.name AS "部门"
  
 
  

       # B点
  
 
  

       ,IF(aspc.payDate IS NOT NULL, "是", "否") AS "是否存在B点数据"
  
 
  

       ,IF(aspc.payDate IS NOT NULL, aspc.payDate, "") AS "B点数据对应时间"
  
 
  

       
  
 
  

   FROM `xxxx`.`u_t_c_s` ut
  
 
  

       INNER JOIN `xxxx`.`t_c_s` tc ON ut.t_c_s_id = tc.id     
  
 
  

       INNER JOIN `xxx`.userinfo ui ON ui.Id = tc.user_id
  
 
  
# 获得A点数据
 
  

       INNER JOIN `xxxx`.account acc ON acc.userId = ui.Id
  
 
  

       INNER JOIN
  
 
  

       (
  
 
  

           SELECT a2.name AS groupName,a1.id AS groupId FROM `xxxx`.`dept` a1,`xxxx`.`dept` a2
  
 
  
a1.pId = a2.id
 
  

       ) dep
  
 
  

       ON dep.groupId = acc.deptId
  
 
  
# 获得B点数据
 
  

       LEFT JOIN
  
 
  

       (
  
 
  

           SELECT MAX(IF(fitstDate IS NOT NULL, fitstDate, secondDate)) AS payDate, userId FROM `xxx`.table_b WHERE state=3 GROUP BY userId
  
 
  

       ) aspc
  
 
  

       ON aspc.userId = ut.user_id
  
 
  

       
  
 
  

   WHERE tc.start_date >= '2019-09-01 00:00:00' AND tc.start_date <= '2019-10-01 00:00:00'
  
 
  

       AND tc.type IN (1, 2) AND tc.`status`=0 AND ut.`status`=0;    
  
 
  
说明:上面sql使用了点技巧
 
  
- S点的技巧:DATE_FORMAT用法,可以直接获取当前时间一个钟后时间,用法见:
  
 
  

   - A点技巧:获取A点数据采用了dept自己跟自己连接的方式来处理,使用pId父Id关联
  
 
  

   - B点技巧:这里采用了跟"2 联表批量更新数据"类似的技巧,max+group by筛选出每一个userId对应最新的那条数据
  
 
  

   额外:其中IINER JOIN是内连,必须要符合的条件(可用于筛选过滤条件),LEFT JOI是外连,用于关联一些可能存在的数据


4 按范围导出多个时间段的数量分布



范围也属于条件的一种,可用CASE..WHEN,或者用区分INTERVAL这个范围更简单,事例如下:

INTERVAL用法:
  
 
  

   SELECT
  
 
  

       INTERVAL(tmp.totalTime,5*60,10*60,20*60,30*60,40*60,50*60,60*60+1) AS TIME,
  
 
  

      COUNT(*)
  
 
  

   FROM
  
 
  

   (
  
 
  
    SELECT MAX(totalTime) AS totalTime,account FROM
 
  
  `xxxx`.`tab_a`
 
  
    WHERE
 
  
    id IN (
 
  
     # 这里是一系列的子查询
 
  
     SELECT xx FROM XXXXXXXX
 
  
  )
 
  
  GROUP BY account
 
  

   ) tmp
  
 
  

   GROUP BY TIME;
  
 
  

   这里的步骤是:
  
 
  

       - 红色部分子查询先用group by account 根据account分组,找出每个account对应的最大totalTime的那条记录
  
 
  

       - 以上面作为结果集返回,然后使用INTERVAL划分区间,表示为如下:
  
 
  

           - 区间为:(tmp.totalTime < 5*60)、(tmp.totalTime >= 5*60 && tmp.totalTime < 10*60)、(tmp.totalTime >= 10*60 && tmp.totalTime < 20*60)....................
  
 
  

       - 然后COUNT(*)就可以把每个区间的数量统计出来
  
 
  

  
 
  

   CASE..WHEN用法(作用与上面一致):
  
 
  

   SELECT
  
 
  

   CASE
  
 
  

       totalTime
  
 
  

       WHEN totalTime = 0 THEN
  
 
  

       '0分钟'
  
 
  

       WHEN 5>totalTime >= 0 THEN
  
 
  

       '5分钟'
  
 
  

       WHEN 10>totalTime >= 5 THEN
  
 
  

       '10分钟'
  
 
  

       WHEN 20>totalTime >= 10 THEN
  
 
  

       '20分钟'
  
 
  

       WHEN 30>totalTime >= 20 THEN
  
 
  

       '30分钟'
  
 
  

       WHEN 40>totalTime >= 30 THEN
  
 
  

       '40分钟'
  
 
  

       WHEN 50>totalTime >= 40 THEN
  
 
  

       '50分钟'
  
 
  

       WHEN 60>totalTime >= 50 THEN
  
 
  

       '60分钟'
  
 
  

     END AS time,
  
 
  

     count(*)
  
 
  

   FROM
  
 
  

   (
  
 
  

       SELECT MAX(totalTime) AS totalTime,account FROM
  
 
  

       `xxx`.`tab_a`
  
 
  

           WHERE
  
 
  

             id IN (
  
 
  

                   SELECT MAX(totalTime) AS totalTime,account FROM
  
 
  

                     `xxxx`.`tab_a`
  
 
  

                       WHERE
  
 
  

                       id IN (
  
 
  

                        # 这里是一系列的子查询
  
 
  

                        SELECT xx FROM XXXXXXXX
  
 
  

                     )
  
 
  

                     GROUP BY account     
  
 
  

             )
  
 
  

   )
  
 
  

   GROUP BY
  
 
  

   CASE
  
 
  

       totalTime
  
 
  

       WHEN totalTime = 0 THEN
  
 
  

     '0分钟'
  
 
  

     WHEN 5>totalTime >= 0 THEN
  
 
  

       '5分钟'
  
 
  

     WHEN 10>totalTime >= 5 THEN
  
 
  

       '10分钟'
  
 
  

       WHEN 20>totalTime >= 10 THEN
  
 
  

       '20分钟'
  
 
  

       WHEN 30>totalTime >= 20 THEN
  
 
  

       '30分钟'
  
 
  

       WHEN 40>totalTime >= 30 THEN
  
 
  

       '40分钟'
  
 
  

       WHEN 50>totalTime >= 40 THEN
  
 
  

       '50分钟'
  
 
  

       WHEN 60>totalTime >= 50 THEN
  
 
  

       '60分钟'  
  
 
  

     END;

 


总结:mysql性能毕竟还是不够高,使用连接的时候并没有使用hash连接,就像有一次我写了一条很多left join的sql,结果使用mysql导出要半个钟左右,后改改用分布式的SQL查询引擎(Presto),导出仅需十几秒,类似这些工具也可以多采用。

更多待续~~~~~~~

标签:totalTime,10,SQL,WHEN,60,mysql,写法,id,SELECT
From: https://blog.51cto.com/u_13854513/7954273

相关文章

  • MySQL 命令行 导出数据 加状态判断 导出excel格式
      SELECTuser.userid,department.`name`,user.username,user.name,user.`email`,keyusage.`productname`,keyusage.`status`,(casewhenkeyusage.status=1then'申请激活'whenkeyusage.status=2then'激活成功'else'激活失败'end)asflag,IN......
  • mysql SQL优化的常用手段有哪些?
    mysqlSQL优化的手段有哪些?1.explain输出执行计划2.in和notin要慎用3.少用select*4.where及orderby涉及的列上建立索引,如果排序字段没有用到索引,就尽量少排序5.可以在程序中排序。6.where子句中避免isnull/isnotnull,7.应尽量避免在where!=或<>or,函数操作......
  • 29、Flink SQL之DESCRIBE、EXPLAIN、USE、SHOW、LOAD、UNLOAD、SET、RESET、JAR、JOB
    文章目录Flink系列文章四、SHOW语句1、java示例2、FlinkSQLcli示例3、showtables1)、语法2)、示例4、SHOWCREATETABLE5、SHOWCOLUMNS1)、语法2)、示例6、SHOWJARS7、SHOWJOBS五、LOAD语句1、语法2、Java示例3、FlinkSQLCli示例六、UNLOAD语句1、语法2、java示例3、Flink......
  • 29、Flink SQL之DESCRIBE、EXPLAIN、USE、SHOW、LOAD、UNLOAD、SET、RESET、JAR、JOB
    Flink系列文章1、Flink部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接13、Flink的tableapi与sql的基本概念、通用api介绍及入门示例14、Flink的tableapi与sql之数据类型:内置数据类型以及它们的属性15、Flink的tableapi与s......
  • Mysql三大存储引擎
    1、MyISAM(对事务支持不好,容易产生死锁)在5.5版本以前是数据库的默认存储引擎。MyISAM不支持事务和外键,适用于对事务完整性没有要求或者以select、insert为主的应用 2、InnoDB(对事务支持好)InnoDB提供了具有提交、回滚和崩溃恢复能力的事务安全。对比MyISAM写的......
  • Ubuntu 安装MySql
    1.安装sudoaptinstallmysql-serversudoaptinstallmysql-cient启动服务:windows启动:netstartmysql服务名停止:netstopmysql服务名mac启动:mysql.serverstart停止:mysql.serverstoplinux:关闭mysql服务:servicemysqlstop启动mysql服务:servicemysql......
  • 用惨痛教训换来的156条MySQL设计规约
    怎么才能很好地避免低级故障?以下规范在大型互联网公司经过了充分验证,尤其适用于并发量大、数据量大的业务场景。 在设计数据库技术方案时,我们是有自己的设计理念或者原则,还是更多依据直觉去设计?是否曾经懊悔线上发生过的一次低级故障?是否思考过怎样才能避免?......
  • SQL语句的基本使用5-多值子查询
    这个作业属于哪个课程https://edu.cnblogs.com/campus/uzz/cs3这个作业要求在哪里https://edu.cnblogs.com/campus/uzz/cs3/homework/13074这个作业的目标SQL语句的基本使用5-多值子查询1.在student_info表中查找与“刘东阳”性别相同的所有学生的姓名、出生日......
  • MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%?
    MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%?前言上篇文章MySQL字段的时间类型该如何选择?千万数据下性能提升10%~30%......
  • 泛微E-Office json_common.php文件存在sql注入漏洞
    漏洞简介泛微e-office为企业办公提供丰富应用,覆盖常见协作场景,开箱即用。满足人事、行政、财务、销售、运营、市场等不同部门协作需求,帮助组织高效人事管理。系统json_common.php文件存在SQL注入漏洞漏洞复现fofa语法:app="泛微-EOffice"登录页面如下:POC:POST/building/......