SQL数据统计总结

写复杂的sql语句时,尽量别用分页  count(0)出现可能使用分页

SQL数据统计总结_第1张图片

 1、统计本级单位以及下级数据

方法一:先子表用count函数统计数据  再配合find_in_set函数 、sum函数统计全部数据。count统计本级数据,sum配合find_in_set是同统计本级以及子级的数据

方法二:直接使用count配合find_in_set再加上判断FIND_IN_SET( dept.id, t.parent_path )来统计本级和本级及其下级数据

SELECT
	dept.id,
//本级数据
	count( CASE WHEN FIND_IN_SET( dept.id, t.parent_path )= 1 THEN 1 END ) bdw,
//本级数据及下级数据
	count( CASE WHEN FIND_IN_SET( dept.id, t.parent_path )> 0 THEN 1 END ) lj 
FROM
	sys_department dept
	LEFT JOIN (
	SELECT
		tq.org_Id,
		sd.parent_path,
		sd.id deptId 
	FROM
		`tq_meet` tq
		LEFT JOIN sys_department sd ON tq.org_id = sd.id 
	) t ON FIND_IN_SET( dept.id, t.parent_path )> 0 
GROUP BY
	dept.id

 先用count统计数量再用sum计算和

  select fresult.*
        from (
        select sd.id ,sd.`name` deptName,
        IFNULL(sum(result.PersuasiveNum),0) PersuasiveNum,
        IFNULL(sum(result.DsrgzdwNum),0) DsrgzdwNum
        from
        sys_department sd
        left join (
        select dTable.create_dept_id,dept.parent_path,dTable.PersuasiveNum PersuasiveNum,dTable.DsrgzdwNum DsrgzdwNum
        from (
        SELECT
        td.create_dept_id,
        count( td.create_dept_id ) PersuasiveNum,
        count(case when td.dsr_gzdw IS NOT NULL
        and td.dsr_gzdw != '' then 1 end) DsrgzdwNum
        FROM
        tq_ddcwf td
        
        GROUP BY
        td.create_dept_id
        )dTable
        left join sys_department dept on dTable.create_dept_id =dept.id
        ) result on FIND_IN_SET(sd.id,result.parent_path)>0
        where sd.id is not null and sd.status=1
        GROUP BY sd.id
        ) fresult
        order by fresult.PersuasiveNum desc

3、传入部门id查出本级及其所以下级的部门id 用来实现统计数据  最好添加上

GROUP BY td.create_dept_id来分类
  
        and td.create_dept_id in
        (select id from
        (
        with recursive departments as
        (
        select a.id,a.name,a.parent_id,b.name as parent_name
        from sys_department a
        left join sys_department b on a.parent_id=b.id
        where a.id in (${deptId})
        union all
        select bb.id,bb.name,bb.parent_id,bb.parent_name from
        (
        select a.id,a.name,a.parent_id,b.name as parent_name
        from sys_department a
        left join sys_department b on a.parent_id=b.id
        ) as bb,departments as h where h.id=bb.parent_id
        )
        select dep.id,dep.name,dep.parent_id,dep.parent_name from departments as dep
        ) xx
        )
      

 此方法的前提是表有parent_path这个字段,以下为生成此字段

//更新所有单位的上级路径
sysDepartmentMapper.updataParentPath(new HashMap<>());


//mapper文件
int updataParentPath(HashMap map);


//xml代码

    update sys_department sd
    set sd.parent_path =getParentList('sys_department', sd.id)

 getParentList为数据库中的函数。

CREATE DEFINER=`root`@`%` FUNCTION `getParentList`(tableName varchar(64),rootId varchar(100)) RETURNS varchar(1000) CHARSET utf8
BEGIN 
DECLARE fid varchar(100) default ''; 
DECLARE str varchar(4000) default rootId; 
 
IF tableName = 'sys_department' THEN 
WHILE rootId is not null  do 
	SET fid =(SELECT parent_id FROM sys_department WHERE id = rootId); 
	IF fid is not null THEN 
		SET str = concat(str, ',', fid); 
		SET rootId = fid; 
	ELSE 
		SET rootId = fid; 
	END IF; 
END WHILE; 
END IF; 

return str;
END

 update sys_department sd
        set sd.parent_path =getParentList('sys_department', sd.id)
com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Data too long for column 'str' at row 1

当数据库中数据父子结构乱的时候可用以下查出结构混乱的数据并删除

SELECT * FROM sys_department depart 
LEFT JOIN sys_department sd2 on depart.parent_id=sd2.id
LEFT JOIN sys_department sd3 on sd2.parent_id=sd3.id
LEFT JOIN sys_department sd4 on sd3.parent_id=sd4.id
LEFT JOIN sys_department sd5 on sd4.parent_id=sd5.id
LEFT JOIN sys_department sd6 on sd5.parent_id=sd6.id
WHERE depart.id=sd2.id or depart.id=sd3.id or depart.id=sd4.id or depart.id=sd5.id or depart.id=sd6.id 

 统计还有生成临时表在统计

  CREATE TEMPORARY TABLE IF NOT EXISTS tempresult AS (
    select count(CASE WHEN YEARWEEK(td.create_time,1) = YEARWEEK(now(),1)-1 THEN 0 END) lastWeekSum,
    count(CASE WHEN YEARWEEK(td.create_time,1) = YEARWEEK(now(),1) THEN 0 END) thisWeekSum,
    count(CASE WHEN MONTH(td.create_time) = MONTH(now()) THEN 0 END) thisMonthSum,
    td.create_dept_name createDeptName,
    td.create_dept_id  createDeptId
    FROM tq_ddcwf td
    
      td.cllx='面包车'
      and (MONTH(td.create_time) = MONTH(now()) or YEARWEEK(td.create_time,1) = YEARWEEK(now(),1)-1 or YEARWEEK(td.create_time,1) = YEARWEEK(now(),1))
      and td.hzrs>4
      
        and td.create_dept_id in
        (select id from
        (
        with recursive departments as
        (
        select a.id,a.name,a.parent_id,b.name as parent_name
        from sys_department a
        left join sys_department b on a.parent_id=b.id
        where a.id in (${deptId})
        union all
        select bb.id,bb.name,bb.parent_id,bb.parent_name from
        (
        select a.id,a.name,a.parent_id,b.name as parent_name
        from sys_department a
        left join sys_department b on a.parent_id=b.id
        ) as bb,departments as h where h.id=bb.parent_id
        )
        select dep.id,dep.name,dep.parent_id,dep.parent_name from departments as dep
        ) xx
        )
        GROUP BY td.create_dept_id
      
    
    );

    SELECT
    IFNULL( SUM( t.lastWeekSum ), 0 ) AS lastWeekSum,
    IFNULL( SUM( t.thisWeekSum ), 0 ) AS thisWeekSum,
    IFNULL( SUM( t.thisMonthSum ), 0 ) AS thisMonthSum,
    sys.NAME AS createDeptName
    FROM
    sys_department sys
    RIGHT JOIN (
    SELECT
    temp1.lastWeekSum,
    temp1.thisWeekSum,
    temp1.thisMonthSum,
    temp1.createDeptName,
    temp1.createDeptId,
    sd.parent_path,
    sd.parent_id
    FROM
    tempresult temp1
    LEFT JOIN sys_department sd ON sd.id = temp1.createDeptId
    ) t ON FIND_IN_SET( sys.id, t.parent_path )> 0
    
      
        sys.parent_id is null or sys.parent_id =''
      
    
    GROUP BY
    sys.id;

2、根据日期统计统计多张表

WITH recursive dates AS (
  SELECT DATE('开始时间') AS date
  UNION ALL
  SELECT date + INTERVAL 1 DAY
  FROM dates
  WHERE date < DATE('结束时间')
), table1_data AS (
  SELECT DATE(create_time) AS date, SUM(value) AS total_value
  FROM table1
  WHERE DATE(create_time) BETWEEN DATE('开始时间') AND DATE('结束时间')
  GROUP BY DATE(create_time)
), table2_data AS (
  SELECT DATE(create_time) AS date, COUNT(*) AS total_count
  FROM table2
  WHERE DATE(create_time) BETWEEN DATE('开始时间') AND DATE('结束时间')
  GROUP BY DATE(create_time)
), table3_data AS (
  SELECT DATE(create_time) AS date, AVG(price) AS average_price
  FROM table3
  WHERE DATE(create_time) BETWEEN DATE('开始时间') AND DATE('结束时间')
  GROUP BY DATE(create_time)
)
SELECT dates.date,
       COALESCE(t1.total_value, 0) AS table1_total_value,
       COALESCE(t2.total_count, 0) AS table2_total_count,
       COALESCE(t3.average_price, 0) AS table3_average_price
FROM dates
LEFT JOIN table1_data t1 ON dates.date = t1.date
LEFT JOIN table2_data t2 ON dates.date = t2.date
LEFT JOIN table3_data t3 ON dates.date = t3.date
ORDER BY dates.date;

实战

WITH recursive dates AS (
  SELECT DATE('2023-08-15') AS date
  UNION ALL
  SELECT date + INTERVAL 1 DAY
  FROM dates
  WHERE date < DATE('2023-08-18')
), table1_data AS (
 SELECT
			DATE( create_time ) AS date,
			count( CASE WHEN cllx = '行人' OR cllx = '电动二轮车' THEN 1 END ) AS 'xingrenOrdderlun',
			count( CASE WHEN cllx = '三轮' OR cllx = '四轮' THEN 1 END ) AS 'sanlunOrsilun',
			count( CASE WHEN cllx = '面包车' THEN 1 END ) AS 'mianbaoche',
			count( CASE WHEN cllx = '电动车临牌' THEN 1 END ) AS 'ddclinpai' 
		FROM
			tq_ddcwf 
  WHERE DATE(create_time) BETWEEN DATE('2023-08-15') AND DATE('2023-08-18')
  GROUP BY DATE(create_time)
), table2_data AS (
  SELECT
		DATE( create_time ) AS date,
		IFNULL( COUNT( 1 ), 0 ) AS 'sjmyjd' 
	FROM
		tq_sjmyjd_table 
  WHERE DATE(create_time) BETWEEN DATE('2023-08-15') AND DATE('2023-08-18')
  GROUP BY DATE(create_time)
), table3_data AS (
 SELECT
		DATE( create_time ) AS date,
		IFNULL( COUNT(*), 0 ) AS 'wjaqd' 
	FROM
		tq_wjaqd 
  WHERE DATE(create_time) BETWEEN DATE('2023-08-15') AND DATE('2023-08-18')
  GROUP BY DATE(create_time)
)
SELECT dates.date,
       COALESCE(t1.xingrenOrdderlun, 0) AS xingrenOrdderlun,
			 COALESCE(t1.sanlunOrsilun, 0) AS sanlunOrsilun,
			 COALESCE(t1.mianbaoche, 0) AS mianbaoche,
			 COALESCE(t1.ddclinpai, 0) AS ddclinpai,
       COALESCE(t2.sjmyjd, 0) AS sjmyjd,
       COALESCE(t3.wjaqd, 0) AS wjaqd
FROM dates
LEFT JOIN table1_data t1 ON dates.date = t1.date
LEFT JOIN table2_data t2 ON dates.date = t2.date
LEFT JOIN table3_data t3 ON dates.date = t3.date
ORDER BY dates.date;

SQL数据统计总结_第2张图片

日期中没有的数据也会实现为0

3、通过构造mybatis返回类型结构来实现多表查询一条数据中带一个list数据

SQL数据统计总结_第3张图片

SQL数据统计总结_第4张图片

SQL数据统计总结_第5张图片


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
      
      
      
      
    
  


  

上面使用嵌套结果映射 但分页不支持嵌套结果映射可以修改为嵌套select可参考

分页导致Mybatis数据不一致(使用了关联查询collection)_高树悲风的博客-CSDN博客

 4、with as 提取临时表别名

SQL数据统计总结_第6张图片

你可能感兴趣的:(sql,数据库,mysql)